Monday, 8 December 2014

Method Overloading resolution in Java

Background

Instead of giving an overview of what this post entails let me give you a quick problem to solve. Lets say you have few methods

public static void execute( int data) {System.out.println("int")}
public static  void execute( short data) {System.out.println("short")}
public static  void execute( Object data) {System.out.println("object")}
public static  void execute( String data) {System.out.println("string")}


and I call following methods - 

public static void main(String[] args) {
    byte byt = 3;
    execute(byt); // 1st call
    execute(10); // 2nd call
    Integer i = 6;
    execute(6); // 3rd call
    execute("Test"); // 4th call
}

What would be the output ?
It would be - 

short
int
object
string

Surprised? Wondering ?

Will solve the mystery in a minute :). Lets get our basics clear first and then there would be no need for me to go ahead and explain the outputs.

Few points to note about the question -
  1. The methods you see have same name, return type but different types of arguments. This is called method overloading. For more details refer Overriding Methods in Java - How it works?
  2. Next we are calling methods some of which that do not exactly match the ones which are defined. Like calling execute() with byte 3. There is no method which takes byte as argument. But there is short, int and even Object argument methods that are compatible. Note the word "compatible" but only one is chosen from it - and we saw it was short in this case. Java as all programming languages has rules which dictates these things which is exactly what we will see in some time.

Rules for method overloading resolution

  1.  Java Compiler always tries to choose the most specific method available with least number of modifications to the arguments.
  2. Next point is about Boxing / Unboxing. Java developers wanted the old code to work exactly the same a sit used to work before boxing / unboxing.
  3. With points 1 and 2 in mind the order in which preference is given is -

    Widening (size wise)[Minimum first] > Boxing/Unboxing > variable arguments.

 Primitive types sizes in Java

  • byte: The byte data type is an 8-bit signed two's complement integer.
  • short: The short data type is a 16-bit signed two's complement integer.
  • int: By default, the int data type is a 32-bit signed two's complement integer.
  • long: The long data type is a 64-bit two's complement integer. 
  • float: The float data type is a single-precision 32-bit IEEE 754 floating point.
  • double: The double data type is a double-precision 64-bit IEEE 754 floating point.
  • boolean: The boolean data type has only two possible values: true and false.
  • char: The char data type is a single 16-bit Unicode character.

Primitive types default values in Java



Now give the question in backgrounds section another try.

With above rules in mind lets try to solve the question posted at the top of this post.

First call was

byte byt = 3;
execute(byt); // 1st call

As per above rule most preferred was would be widening. There are two options here. Widen byte (8bit) to a short (16 bit) or an int (32 bit). Widening with lowest size is preferred (which is short in this case) and hence we got short printed.

Next is

execute(10); // 2nd call

and is a direct call as we have execute method with int parameter. So int is printed.

Next we have

Integer i = 6;
execute(6); // 3rd call

Since we do not have a method with Integer as argument we will go for next best case and that is polymorphic superclass. Object is superclass of all objects implicitly. So we get object printed.

Lastly we have

execute("Test"); // 4th call

Again we have execute method with String which is chosen here. Again straight forward.

Note : Widening is preferred over boxing/unboxing which is preferred over variable arguments. By variable arguments I mean something like

public void execute (int ...x)

Hope this clarifies all doubts regarding our original question.

Note : Java Compilation will fail if there are no matches or ambiguous matches for a function call.

Example of no matches : 

Methods available are

public static  void execute( short data) {System.out.println("short")}
public static  void execute( byte data) {System.out.println("byte")}

and you call

execute (10) // execute (int)

Example of ambiguous matches : 


Methods available are

public static  void execute( int data1, long data2) {System.out.println("int-long")}
public static  void execute( long data1, int data2) {System.out.println("long-int")}

and you call

execute (1,2) // execute (int,int)

Related Links


Sunday, 30 November 2014

Starting a new Process programmatically from Java

Background

In this post we will see how we can run any process from java programmatically. In specific I will show how can we compile a java file from a Java process. We can very well use Runtime.getRuntime().exec() method to start the process but in this post I am going to demonstrate using ProcessBuilder class.

Code

    public static void executeJavacCommand() throws IOException {

        List<String> paramsExecute = new ArrayList<String>();
        paramsExecute.add("C:\\Program Files\\Java\\jdk1.6.0_31\\bin\\javac.exe");
        paramsExecute.add("-cp");
        paramsExecute.add(".");
        paramsExecute.add("HelloWorld.java");
        ProcessBuilder pBuilder = new ProcessBuilder(paramsExecute);
        Process process = pBuilder.start();
        Reader reader = new InputStreamReader(process.getErrorStream());
        int ch;
        while((ch = reader.read())!= -1)
            System.out.print((char)ch);
        reader.close();

    }

Note1 : In above code I am only printing the error stream of the process but you can manipulate the output stream as well as provide input stream to the process.
Note 2:  You can also see my previous post on how to get the java executable paths. You can programmatically derive those and use it in above code.


Related Links

Finding Java home programatically from Java program

Background

There might be various scenarios in which you might need to get the path of java executable. For example to lets say start java program from withing Java code. In this post we will see how can we achieve that. I will demonstrate a method to find the JAVA_HOME that is usually the JDK directory. Once you have that it is easy to get executable. For eg javac will be in JAVA_HOME/bin/javac.exe

Code

public class JavaHomeTest{

    public static void main(String args[]) throws IOException {
        System.out.println(getJDKDir());
    }

    public static String getJDKDir() {
        File javaHome = new File( System.getProperty( "java.home" ) ).getParentFile();
        File jdkDirectory = null;
        if( javaHome.getName().contains( "jdk" ) ) { 
            //happens in IntelliJ
            jdkDirectory = javaHome;
        } else { 
            //General Scenario - eclipse / command line
            File[] childDirs = javaHome.listFiles();
            for(File file : childDirs) {
                if(file.getName().contains("jdk")) {
                    jdkDirectory = file;
                    break;
                }
            }
            
        }
        return jdkDirectory.getAbsolutePath();
    }

}


Output : 

I am running Windows. The output that I get is 'C:\Program Files (x86)\Java\jdk1.7.0_55'. Code is same for Linux as well. You will get your Java directory.

Saturday, 29 November 2014

How to delete a directory in Java

Background

Well lately I have written a lot of code for file manipulation, I/O etc. So let me take this post to show how can we create or delete directories. Well Java provides APIs for them so it should be pretty straightforward to understand. Important point to look forward is that if you are deleting a directory and it has more files in it then the directory will not get deleted unless all it's children are deleted recursively.  Note File as a Java object can represent either a file or a directory. You can use File 's class isDirectory() method Eg.

        File file = new File("C:\\Users\\athakur\\Downloads");
        if(file.isDirectory()) {
            System.out.println("File is a directory");
        }


Now lets get to creating and deleting directories/files.



Creating a File

To create a file we can use createNewFile() method. Eg - 

        File file = new File("C:\\Users\\athakur\\Downloads\\abc.txt");
        if(!file.exists()) {
            file.createNewFile();
        }

Creating a Directory

To create a directory first create a File object and then call mkdir() on it. Eg -

        File file = new File("C:\\Users\\athakur\\Downloads\\Movies");
        if(!file.exists()) {
            file.mkdir();
        }

Deleting a file/directory

To delete a file or a directory we have to use delete() method. As stated in introductory paragraph if directory has data that data needs to be deleted first. "rm -rf *" does not work in java :).

    public void deleteDirectory(String path) {
        
        File file  = new File(path);
        if(file.isDirectory()){
            String[] childFiles = file.list();
            if(childFiles == null) {
                //Directory is empty. Proceed for deletion
                file.delete();
            }
            else {
                //Directory has other files.
                //Need to delete them first
                for (String childFilePath :  childFiles) {
                    //recursive delete the files
                    deleteDirectory(childFilePath);
                }
            }
            
        }
        else {
            //it is a simple file. Proceed for deletion
            file.delete();
        }
        
    }


Above method will delete complete directory.

Tuesday, 25 November 2014

Install Intellij Idea in Ubuntu

Background

Whichever IDE you use installing it is very easy in Ubuntu. In this post I will show how can we configure Intellij IDEA. Installing Eclipse is also similar. You can see short summary of it in 



Downloading and Installing

  1. Download latest Intellij IDEA from their official site. For me its 'ideaIC-14.0.1.tar.gz'.
  2. Extract the compressed archive to some suitable folder. I will install it in a folder called firefox in my user directory -

    aniket@aniket-Compaq-610:~$ cd firefox/
    aniket@aniket-Compaq-610:~/firefox$ tar xzvf ideaIC-14.0.1.tar.gz
  3. That's pretty much it for downloading and installing part. You can run the IDE by executing idea.sh script file inside the bin folder.

    aniket@aniket-Compaq-610:~/firefox$ cd idea-IC-139.225.3/
    aniket@aniket-Compaq-610:~/firefox/idea-IC-139.225.3$ ./bin/idea.
    sh

Creating launcher for your application

Procedure is same for creating launcher for your executable. I will demonstrate it for IDEA.

aniket@aniket-Compaq-610:~$ cd /usr/share/application/
aniket@aniket-Compaq-610:/usr/share/applications$ sudo gedit idea.desktop


Now add the following lines to it

[Desktop Entry]
Name=IntelliJ IDEA
Comment=IntelliJ IDEA IDE
Exec=/home/aniket/firefox/idea-IC-139.225.3/bin/idea.sh
Icon=/home/aniket/firefox/idea-IC-139.225.3/bin/idea.png
Terminal=false
StartupNotify=true
Type=Application
Categories=Development;IDE;


Above configuration is with respect to my executable path. Change the enteries accordingly. Save the file and run it to launch the application.

Note : Did you notice we put out idea.desktop in '/usr/share/applications' folder. By doing this it will also be accessible from unity search dashboard.



If you remember we had done similar thing for Eclipse. We downloaded the archive file and then created the launcher.

Related Links

t> UA-39527780-1 back to top