Push Notifications

Image
A notification in a message you can display to the user outside of your application's normal UI. When you tell the system to issue a notification, it first appears as an icon in the  notification area . To see the details of the notification, the user opens the  notification drawer . Both the notification area and the notification drawer are system-controlled areas that the user can view at any time. System will also display the notification as a TOAST when user is logged-in along with increment in the notification drawer. Lightweight Event Driven Notification System 1.1      Event Generation The event generation phase happens while processing the response to a user request. As such, we wanted to ensure that there was little or no impact on the response times from where notification is called/generated. To ensure this was the case, all we will do is store the minimum amount of data possible/lightweight message on the queue. We store the min...

Magical Final - Expanded Usage

Most of us are aware of keyword final in java for the following:

  1. Prevent Inheritance by declaring class as final.
  2. Prevent method overriding by making method as final.
  3. Declaring constants.

I am here to let know more advantages of keyword 'FINAL' which are not generally aware of:
  1. More about Final Constants.
  2. Conditional Compilation

More About Final Constants

Primitive (int, char, float etc) other than arrays are substituted at compile time with their values, if you change a final that is used by other classes, you must remember to recompile those other classes or your change will not take effect. The same rule applies to constants of type java.lang.String. Although String is a constructed type, it is also substituted at compile time. All constructed types other than String, mutable or not, are not substituted at compile time. To understand how this works

Consider the following code fragment:


package com.dapinder.practice;

public class FinalConstantSubstitute {

/** A string constant */
public final static String STRING_VAR = "Dapinder's Blog";

/** An int constant. */
public final static int INT_VAR = 15;

/** A double constant. */
public final static double DOUBLE_VAR = 13.23d;

/** An array constant. */
public final static int[] ARRAY_VAR = new int[] { 2, 2, 2, 2, 2, 2 };

/** A Wrapper constant. */
public final static Integer A_OTHER_WRAPPER = new Integer(10);

public static void main(String[] args) {

System.out.println(STRING_VAR);
System.out.println(INT_VAR);
System.out.println(DOUBLE_VAR);
System.out.println(ARRAY_VAR);
System.out.println(A_OTHER_WRAPPER);

}
}

Once the compiler sees code such as this, it optimizes it and starts substituting out the primitives and String objects. ByteCode view of the FinalConstantSubstitute post compilation:

Be cautious of using final constants when accessing in some other class. Since above is a single class so its not getting noticed but if you use the declared public constants in some other class, then changing of constant, you have to recompile the class which is using the constant as well. 
Check below for example:
package com.dapinder.practice;

public class FinalConstantSubstituteMain {

/**
* The class using declared final constants.
* @param args
*/
public static void main(String[] args) {
 
  /** Substituted values */
System.out.println(FinalConstantSubstitute.STRING_VAR);
System.out.println(FinalConstantSubstitute.INT_VAR);
System.out.println(FinalConstantSubstitute.DOUBLE_VAR);
System.out.println(FinalConstantSubstitute.ARRAY_VAR);
System.out.println(FinalConstantSubstitute.A_OTHER_WRAPPER);

}
}

Here compiler will substitute the constant's values from  FinalConstantSubstitute class. For example, change of constant STRING_VAR to some other value say "Google" will not reflect in FinalConstantSubstituteMain class unless FinalConstantSubstituteMain is compiled. The reason is obvious since substitution happens at compile time and is done by the compiler.


Conditional Compilation

This will amaze you when you think how final variables can provide a way where certain lines get conditional compilation based on a particular condition. This can actually save on most debugging code in production and will improve the performance as well.
To understand its power, lets take an example:



package com.dapinder.practice;

public class ConditionalFinal {

private static boolean isLoggingEnabled = false;

/**
* @param args
*/
public static void main(String[] args) {
if (isLoggingEnabled) {
System.out.println("Statment 1");
}
if (isLoggingEnabled) {
System.out.println("Statment 2");
}
if (isLoggingEnabled) {
System.out.println("Statment 3");
}
if (isLoggingEnabled) {
System.out.println("Statment 4");
}
}
}

Please note that variable isLoggingEnabled  is not declared FINAL here.
Check below the bytecode view:

Please note that all IF conditions are very well referencing the variable and if the isLoggingEnabled is true, i will print on the console and when false it wont print but yet have although less on performance as it will check each conditional IF statement. 
This is fine and at first glance does not seem expensive but in production where one method is called by millions of threads and multiple times, this can get expensive.

Most of us know and have used Log4J and we know not all logging statements are turned on in production. Most of us even do a isDebugEnabled before logging a debug statement.
However When using the isDebugEnabled( ) method in Log4J, the cost is much more than one comparison per if statement.

Now check by converting the isLoggingEnabled variable into a FINAL variable:

package com.dapinder.practice;

public class ConditionalFinal {

private static final boolean isLoggingEnabled = false;

/**
* @param args
*/
public static void main(String[] args) {
if (isLoggingEnabled) {
System.out.println("Statment 1");
}
if (isLoggingEnabled) {
System.out.println("Statment 2");
}
if (isLoggingEnabled) {
System.out.println("Statment 3");
}
if (isLoggingEnabled) {
System.out.println("Statment 4");
}
}
}

By converting the isLoggingEnabled attribute into a final attribute, you have told the compiler that whenever it sees isLoggingEnabled, it should replace it with false as per substitution principle explained above.

One more important point here.
Most of us do get WARNING in any IDE (say Eclipse) whenever a piece of code is unreachable. Here compiler applies the same principle and removes all those statement which are meant to be unreachable or will never execute.
Here, in above example, all these logging statements will disappear.





Comments

Post a Comment

Popular posts from this blog

Creating your Cache with LRU Algorithm

Heap Dump Analysis

Understanding OutOfMemory Issues