Monday, 29 May 2017

Nested class and Inner class in Java

In Java programming language you can define a class within another class. Such a class is called nested class.

Nested class categories

Nested classes are divided into two categories -

  • Static nested classes - Nested classes that are declared static are called static nested classes.
  • Non-static nested classes - Nested classes that are not static are called Non-static nested classes. They are known better as inner classes.

General form of static nested class

class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
   
}

General form of inner class

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

Access modifiers for Nested classes

Since nested class is a member of its enclosing class, a nested class can have any of the access modifiers; private, public, protected, or package private. Note that outer classes can only be declared public or package private.

Benefits of using Nested Classes

  1. Nested classes provide a way to logically group classes that are only used in one place.
    If a class is useful to only one other class, then it makes sense to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
  2. It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
  3. It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.

Static nested class example code

public class NestedDemo {
 int num = 10;
 public static class Nested{
  NestedDemo nd = new NestedDemo();
  private int quantity = 10;
  void msg(){
   System.out.println("data is "+ nd.num * quantity);
  }
 }
 public static void main(String[] args) {
  NestedDemo.Nested nested = new NestedDemo.Nested();
  nested.msg();
 }
}

Output

data is 100

Points to note about static nested class

  1. Just like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class, it can use them only through an object reference.
  2. Static nested classes are accessed using the enclosing class name: NestedDemo.Nested

Inner class

An inner class is a nested class that is not static. Inner class has access to all the members (fields and methods) of the outer class including those with access modifier as private.

Let’s see a simple inner class example here to make it clearer.

Inner class example code

In this example there is a OuterClass with one private field, a method createInner() and an inner class InnerClass. Inner class has one method displayMsg() which takes String as argument.
class OuterClass {
 private int outerVar = 12;
 // Inner class
 class InnerClass{
  void displayMsg(String msg){
   System.out.println("Message is - " + msg);
   System.out.println("Outer class variable - " + outerVar);
  }
 }
 
 void createInner(){
  InnerClass ic = new InnerClass();
  ic.displayMsg("Calling From a method with in the Outer class");
 }
}

public class ICDemo {
 public static void main(String[] args) {
  OuterClass oc = new OuterClass();
  oc.createInner();
  // Creating inner class object using outer class object
  OuterClass.InnerClass oic = oc.new InnerClass();
  oic.displayMsg("Calling from outside the OuterClass scope");
 }
}

Output

Message is - Calling From a method with in the Outer class
Outer class variable - 12
Message is - Calling from outside the OuterClass scope
Outer class variable - 12

Points to note

There are several points of interest to note here about the inner classes –

  1. From the output you can see that inner class has access to fields and methods of the outer class, even if they are private. In the displayMsg() method of the inner class outerVar variable is accessed which is private and resides with in the scope of outer class.
  2. If you want to make an object of the inner class with in a non-static method of the outer class you don’t need to qualify it with Outer class name. Since createInner() method is a method of the outer class and it is not static you can create an object of the inner class directly.
  3. If you want to make an object of the inner class outside the scope of the outer class or from a method with in the outer class which is static you have to qualify inner class with the outer class so the type of the object would be specified as OuterClassName.InnerClassName. You can see example of object creation of inner class that way in the main method as it resides in another class ICDemo.
  4. An inner class can be private, public, protected or package-private. Note that normal class can only be public or package-private (default).

Types of inner classes

Apart from non-static nested class (also known as member inner class) there are two additional types of inner classes.

  • Local inner class
  • Anonymous inner class

Local inner class

Local inner classes are inner classes that can be defined within a block, here block means any group of zero or more statements between balanced braces. Generally you will find local inner classes defined within a method body.

Local inner class example

Let’s see an example of local inner class where inner class is defined in the method msg. Here Local inner class is also implementing an interface Message.

package org.prgm;
// Interface
interface Message{
 String readMsg();
}

class Outer {
 private int outerVar = 12;
 public Message msg(String str){
  // Local variable - it has to be final or
  // effectively final
  String hello = "Hello ";
  // Local Inner class
  class InnerMsg implements Message{
   
   private String msg;
   
   InnerMsg(String msg){
    this.msg = msg;
   }
   @Override
   // implementing interface method
   public String readMsg() {
    //hello = "Hi";
    System.out.println("I can read outer class variable its value is - " + outerVar );
    return hello + msg;
   }
   
  }
  return new InnerMsg(str);
  
 }

}
public class ICLocalDemo {

 public static void main(String[] args) {
  Outer outer = new Outer();
  Message message = outer.msg("Local Inner Class");
  String temp = message.readMsg();
  System.out.println("temp -- " + temp);
  
 }

}

Output

I can read outer class variable its value is - 12
temp -- Hello Local Inner Class

Points to note

There are several points of interest in the above code so let’s go through those points and try to get a better explanation.

  1. Here inner class InnerMsg is defined with in the method msg that is why it is local inner class as it is local to the method msg.
  2. Local inner class can access members of the enclosing class, you can see that int variable outerVar is accessed with in the inner class InnnerMsg.
  3. A local class has access to local variables (variables defined inside the method body). However, a local class can only access local variables that are declared final (before Java 8).
  4. Starting in Java SE 8, local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final. In the method readMsg() if you uncomment the line - //hello = "Hi"; You will get the error “Local variable hello defined in an enclosing scope must be final or effectively final” if you are running this code in Java 8. If you are using version lesser than 8 then it will ask you to declare hello as final.
  5. In the above code one thing to note is that inner class implements an interface. Doing that you are abiding to a very important point of object oriented programming – Abstraction. If you have noticed the return type of the method msg is interface Message. That way your implementation of the inner class is completely hidden.

Anonymous inner class

Anonymous inner class is a type of local inner class that has no name. You will always declare anonymous inner class as subclass or as implementation of an interface. Note that you cannot declare constructors in an anonymous class.

Anonymous inner class example code

Let’s implement the same example as above as an anonymous inner class. There is an interface Message and that is implemented as an anonymous inner class with in the method msg.

//Interface
interface Message{
 String readMsg();
}

class MessageOuter {
 private int outerVar = 12;
 public Message msg(String str){
  // Local variable - it has to be final or
  // effectively final
  String hello = "Hello ";
  return new Message(){
   @Override
   public String readMsg() {
    //hello = "Hi";
    System.out.println("I can read outer class variable its value is - " + outerVar );
    return hello + str;
   }
   
  }; // required to have semicolon
 }
}

/**
 * 
 * 
 *
 */
public class ICAnonymousDemo {

 public static void main(String[] args) {
  MessageOuter mo = new MessageOuter();
  Message msg = mo.msg("Anonymous Inner Class");
  System.out.println("Message is - " + msg.readMsg());

 }
}

Output

I can read outer class variable its value is - 12
Message is - Hello Anonymous Inner Class

Points to note

There are several points of interest in the above code so let’s go through those points and try to get a better explanation.

  1. Here inner class with in the method msg is an anonymous inner class. It contains a new operator, name of the interface it is implementing (it can also extend a class), and class declaration body with in the braces.
  2. Because an anonymous class definition is an expression, it must be part of a statement. That is why there is a semicolon after the closing brace.
  3. Anonymous inner class can access members of the enclosing class, you can see that int variable outerVar is accessed with in the method of the anonymous inner class.
  4. Anonymous inner class has access to local variables (variables defined inside the method body). Same rules apply as in the case of local inner class.
  5. You cannot declare constructors in an anonymous class as it has no name.

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


Related Topics

  1. Serialization in Java
  2. Object cloning in java
  3. final in Java
  4. effectively final in Java 8
  5. Lambda expressions in Java 8

You may also like -

>>>Go to Java advance topics page

Wednesday, 24 May 2017

How to untar a file - Java Program

This post shows how to untar a tar file. It has both the steps to first uncompress a .tar.gz file and later untar it.

Using Apache Commons Compress

Apache Commons Compress library is used in the code for untarring a file. You can download it from here – https://commons.apache.org/proper/commons-compress/download_compress.cgi.

Make sure to add commons-compress-xxx.jar in your application’s class path. I have used commons-compress-1.13 version.

Example Code

This Java program has two methods deCompressGZipFile() method is used to uncompress a .tar.gz file to get a .tar file. Using unTarFile() method this .tar file is untarred.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;

public class UnTarDemo {

    public static void main(String[] args) {
        // Path to input file, which is a 
        // tar file compressed to create gzip file
        String INPUT_FILE = "G:\\Test.tar.gz";
        // This folder should exist, that's where
        // .tar file will go
        String TAR_FOLDER = "G:\\TarFile";
        // After untar files will go to this folder
        String DESTINATION_FOLDER = "G:\\Temp";
        UnTarDemo unTarDemo = new UnTarDemo();
        try {
            File inputFile = new File(INPUT_FILE);
            String outputFile = getFileName(inputFile, TAR_FOLDER);
            System.out.println("outputFile " + outputFile);
            File tarFile = new File(outputFile);
            // Calling method to decompress file
            tarFile = unTarDemo.deCompressGZipFile(inputFile, tarFile);
            File destFile = new File(DESTINATION_FOLDER);
            if(!destFile.exists()){
                 destFile.mkdir();
            }
            // Calling method to untar file
            unTarDemo.unTarFile(tarFile, destFile);
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /**
     * 
     * @param tarFile
     * @param destFile
     * @throws IOException
     */
    private void unTarFile(File tarFile, File destFile) throws IOException{
        FileInputStream fis = new FileInputStream(tarFile);
        TarArchiveInputStream tis = new TarArchiveInputStream(fis);
        TarArchiveEntry tarEntry = null;
        
        // tarIn is a TarArchiveInputStream
        while ((tarEntry = tis.getNextTarEntry()) != null) {
            File outputFile = new File(destFile + File.separator + tarEntry.getName());
            
            if(tarEntry.isDirectory()){
                
                System.out.println("outputFile Directory ---- " 
                    + outputFile.getAbsolutePath());
                if(!outputFile.exists()){
                    outputFile.mkdirs();
                }
            }else{
                //File outputFile = new File(destFile + File.separator + tarEntry.getName());
                System.out.println("outputFile File ---- " + outputFile.getAbsolutePath());
                outputFile.getParentFile().mkdirs();
                //outputFile.createNewFile();
                FileOutputStream fos = new FileOutputStream(outputFile); 
                IOUtils.copy(tis, fos);
                fos.close();
            }
        }
        tis.close();
    }
    
    /**
     * Method to decompress a gzip file
     * @param gZippedFile
     * @param newFile
     * @throws IOException
     */
    private File deCompressGZipFile(File gZippedFile, File tarFile) throws IOException{
        FileInputStream fis = new FileInputStream(gZippedFile);
        GZIPInputStream gZIPInputStream = new GZIPInputStream(fis);
        
        FileOutputStream fos = new FileOutputStream(tarFile);
        byte[] buffer = new byte[1024];
        int len;
        while((len = gZIPInputStream.read(buffer)) > 0){
            fos.write(buffer, 0, len);
        }
        
        fos.close();
        gZIPInputStream.close();
        return tarFile;
                
    }
    
    /**
     * This method is used to get the tar file name from the gz file
     * by removing the .gz part from the input file
     * @param inputFile
     * @param outputFolder
     * @return
     */
    private static String getFileName(File inputFile, String outputFolder){
        return outputFolder + File.separator + 
                inputFile.getName().substring(0, inputFile.getName().lastIndexOf('.'));
    }
}

That's all for this topic How to untar a file - Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Creating tar file and GZipping multiple files - Java Program
  2. Zipping files in Java
  3. Unzipping files in Java
  4. Compressing and Decompressing File in GZIP Format
  5. How to read file from the last line in Java

You may also like -

>>>Go to Java Programs page

Monday, 22 May 2017

Creating tar file and GZipping multiple files - Java Program

If you want to GZIP multiple files that can’t be done directly as you can only compress a single file using GZIP.

For that you will have to archive multiple files into a tar and then compress it to create a .tar.gz compressed file.

Using Apache Commons Compress

Here I am posting a Java program to create a tar file using Apache Commons Compress library. You can download it from here – https://commons.apache.org/proper/commons-compress/download_compress.cgi

Make sure to add commons-compress-xxx.jar in your application’s class path. I have used commons-compress-1.13 version.

Steps for creating tar files

Steps for creating tar files are as follows -

  1. Create a FileOutputStream to the output file (.tar.gz) file.
  2. Create a GZIPOutputStream which will wrap the FileOutputStream object.
  3. Create a TarArchiveOutputStream which will wrap the GZIPOutputStream object.
  4. Then you need to read all the files in a folder.
  5. If it is a directory then just add it to the TarArchiveEntry.
  6. If it is a file then add it to the TarArchiveEntry and also write the content of the file to the TarArchiveOutputStream.

Folder Structure used

Here is a folder structure used in this post to read the files. Test, Test1 and Test2 are directories here and then you have files with in those directories. Your Java code should walk through the whole folder structure and create a tar file with all the entries for the directories and files and then compress it.

Test
  abc.txt
  Test1
     test.txt
     test1.txt
  Test2
     xyz.txt

Example code

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;

public class TarGZIPDemo {

 public static void main(String[] args) {
   String SOURCE_FOLDER = "G:\\Test";
   TarGZIPDemo tGzipDemo = new TarGZIPDemo();
   tGzipDemo.createTarFile(SOURCE_FOLDER);
 }
 
 /**
  * 
  * @param source
  */
 private void createTarFile(String source){
  TarArchiveOutputStream tarOs = null;
  try {
    // Using input name to create output name
    FileOutputStream fos = new FileOutputStream(source.concat(".tar.gz"));
    GZIPOutputStream gos = new GZIPOutputStream(new BufferedOutputStream(fos));
    tarOs = new TarArchiveOutputStream(gos);
    File folder = new File(source);
    File[] fileNames = folder.listFiles();
    for(File file : fileNames){
      System.out.println("PATH " + file.getAbsolutePath());
      System.out.println("File name " + file.getName());
      addFilesToTarGZ(file.getAbsolutePath(), file, tarOs);
    }
   
  } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }finally{
    try {
     tarOs.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
 }
 /**
  * 
  * @param source
  * @param file
  * @param tos
  * @throws IOException
  */
 private void addFilesToTarGZ(String source, File file, TarArchiveOutputStream tos) 
                   throws IOException{
   // New TarArchiveEntry
   tos.putArchiveEntry(new TarArchiveEntry(file, source));
   if(file.isFile()){
     FileInputStream fis = new FileInputStream(file);
     BufferedInputStream bis = new BufferedInputStream(fis);
     // Write content of the file
     IOUtils.copy(bis, tos);
     tos.closeArchiveEntry();
     fis.close();
   }else if(file.isDirectory()){
     // no need to copy any content since it is
     // a directory, just close the outputstream
     tos.closeArchiveEntry();
     for(File cFile : file.listFiles()){
       // recursively call the method for all the subfolders
       addFilesToTarGZ(cFile.getAbsolutePath(), cFile, tos);
    
     }
   }
  
 }
}

That's all for this topic Creating tar file and GZipping multiple files - Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Zipping files in Java
  2. Unzipping files in Java
  3. Compressing and Decompressing File in GZIP Format
  4. How to convert a file to byte array

You may also like -

>>>Go to Java Programs page

Monday, 1 May 2017

Compressing and Decompressing File in GZIP Format - Java Program

You will mainly use GZIP tool to compress and decompress files in Unix systems. Here note that you can only compress a single file using GZIP not multiple files residing in a folder.

Steps to compress a file

In order to compress a file using GZIP the steps are as follows -

  1. For reading the source file (file which has to be GZIPped) create a FileInputStream.
  2. Create a FileOutputStream to the target file (output GZIPped file).
  3. Create a GZIPOutputStream wrapping the FileOutputStream.
  4. Then you just need to read from the input stream and write to the output stream.

Steps to decompress a file

In order to decompress a file using GZIP the steps are as follows -

  1. For reading the compressed file create a FileInputStream.
  2. Wrap that FileInputStream with in a GZIPInputStream.
  3. Create a FileOutputStream to the new file (created on decompressing GZIP file).
  4. Then you just need to read from the input stream and write to the output stream.

Example code for compressing and decompressing file in GZIP format

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class GZipDemo {

 public static void main(String[] args) {
  // Path to file which is gzipped
  String SOURCE_FILE = "G:\\Test\\abc.txt";
  // Path to gzipped output files
  String GZIP_OUTPUT_FILE = "G:\\Test\\abc.gz";
  // File you get after decompressings
  String GZIP_NEW_FILE = "G:\\Test\\newabc.txt";
  
  GZipDemo gZipDemo = new GZipDemo();
  try {
   // Compressing a file
   gZipDemo.compressGZipFile(SOURCE_FILE, GZIP_OUTPUT_FILE);
   
   // decompressing a file
   gZipDemo.deCompressGZipFile(GZIP_OUTPUT_FILE, GZIP_NEW_FILE);
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }
 /**
  * Method to gzip a file
  * @param sourceFile
  * @param outputFile
  * @throws IOException
  */
 public void compressGZipFile(String sourceFile, String outputFile) 
    throws IOException{
  FileInputStream fis = new FileInputStream(sourceFile);
  FileOutputStream fos = new FileOutputStream(outputFile);
  GZIPOutputStream gZIPOutputStream = new GZIPOutputStream(fos); 
  byte[] buffer = new byte[1024];
  int len;
  while((len = fis.read(buffer)) > 0){
   gZIPOutputStream.write(buffer, 0, len);
  }
  
  fis.close();
  gZIPOutputStream.close();
  
 }
 
 /**
  * Method to decompress a gzip file
  * @param gZippedFile
  * @param newFile
  * @throws IOException
  */
 public void deCompressGZipFile(String gZippedFile, String newFile) 
    throws IOException{
  FileInputStream fis = new FileInputStream(gZippedFile);
  GZIPInputStream gZIPInputStream = new GZIPInputStream(fis);
  FileOutputStream fos = new FileOutputStream(newFile);
  byte[] buffer = new byte[1024];
  int len;
  while((len = gZIPInputStream.read(buffer)) > 0){
   fos.write(buffer, 0, len);
  }
  
  fos.close();
  gZIPInputStream.close();
 }

}

That's all for this topic Compressing and Decompressing File in GZIP Format - Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Zipping files in Java
  2. Unzipping files in Java
  3. Reading all files in a folder - Java Program
  4. Writing file in Java

You may also like -

>>>Go to Java Programs page