Topics Covered in this Page
  1. Java Key Words
  2. Access Modifiers
  3. Wrapper Class
  4. Generics
  5. Comparable and Comparator
  6. Garbage Collection
  7. Java Compile-time Vs Run-time
  8. How java works
  9. Class Loader
  10. Exceptions
  11. java.lang and java.util
  12. Memory Model
  13. Array Copy
  14. Serialization
  15. Java Multithreading
Java Key Words Access Modifiers

Wrapper Class
Wrapper classes are used to convert any data type into an object.
Generics
Generics was added in Java 5 to provide compile-time type checking and removing risk of ClassCastException that was common while working with collection classes.
It provides compile time type-safety and ensures that you only insert correct Type in collection and avoids ClassCastException in runtime.
Example:
                List list = new ArrayList();
                list.add("1");
                list.add("string");
                String str = list.get(1);
                System.out.println(str);    // output: string
            
Generics for loop:
                List strings = new ArrayList();
                //... add String instances to the strings list...      
                for(String aString : strings){
                    System.out.println(aString);
                }
            

Comparable and Comparator
Comparable and Comparator both are interfaces and can be used to sort collection elements. It provide single sorting sequence only.

Comparable Interface
Method: compareTo(Object): used to compare the current object with the specified object.
It compares strings on the basis of Unicode value of each character in the strings.
return: >: positive int / ==: 0 / <: negative int

Can used to sort: Comparator Interface
Used to order the objects of user-defined class. It provides multiple sorting sequence
Method: compare(Object obj1,Object obj2) and equals(Object element).
When to use Comparable and Comparator
Comparable: when sorting based on natural order.
Comparator: when sorting based on special ordering.

Garbage Collection
Java Compile-time Vs Run-time
Compile-time is the instance where the code you entered is converted to executable while Run-time is the instance where the executable is running.

What could happen at Compile time?
What could happen at Run time?


How Java works
In general
Class loader
The Java Class loader is a part of the Java Runtime Environment that dynamically loads Java classes into the Java Virtual Machine.

Exceptions
Exception is an event that disrupts the normal flow of the program. It is an object which is thrown at runtime.



Error vs Exception
Error: An Error indicates serious problem that a application should not try to catch. It is impossible to recovery.
Exception: Exception indicates conditions that a application might try to catch.

How JVM handles exceptions

Types of Exception

Throw vs Throws
java.lang and java.util
Java.lang is a package which contains the classes like System, String, String Buffer etc., This package doesn't have to be explicitly imported as they are imported by default.
java.util is a package which contains classes like Date, Vector, Dictionary, hashtable etc., This has to be imported everytime you use it in your program

Memory Model
Stack: Stack memory is responsible for holding references to heap objects and for storing value types. Thread has its own stack. Only exist within the scope of the function, once return, they are destroyed.
Heap: referenced by stack. Objects are created on heap.

Array Copy
Serialization
Serialization is a mechanism of converting the state of an object into a byte stream.
Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory.
Example:
Example of Serialize to a file and Deserialize from the same file.
                import java.io.FileInputStream;
                import java.io.FileOutputStream;
                import java.io.IOException;
                import java.io.ObjectInputStream;
                import java.io.ObjectOutputStream;

                public class SerializationUtil {
                    // deserialize to Object from given file
                    public static Object deserialize(String fileName) throws IOException, ClassNotFoundException {
                        FileInputStream fis = new FileInputStream(fileName);
                        ObjectInputStream ois = new ObjectInputStream(fis);
                        Object obj = ois.readObject();
                        ois.close();
                        return obj;
                    }

                    // serialize the given object and save it to file
                    public static void serialize(Object obj, String fileName) throws IOException {
                        FileOutputStream fos = new FileOutputStream(fileName);
                        ObjectOutputStream oos = new ObjectOutputStream(fos);
                        oos.writeObject(obj);
                        fos.close();
                    }
                }
            
                import java.io.IOException;

                public class SerializationTest {
                    
                    public static void main(String[] args) {
                        String fileName="employee.ser";
                        Employee emp = new Employee();
                        emp.setId(100);
                        emp.setName("Pankaj");
                        emp.setSalary(5000);
                        
                        //serialize to file
                        try {
                            SerializationUtil.serialize(emp, fileName);
                        } catch (IOException e) {
                            e.printStackTrace();
                            return;
                        }
                        
                        Employee empNew = null;
                        try {
                            empNew = (Employee) SerializationUtil.deserialize(fileName);
                        } catch (ClassNotFoundException | IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            

transient keyword in Java
Java Multithreading
Life Cycle of a Thread

                    // Java code for thread creation by extending the Thread class 
                    class MultithreadingDemo extends Thread { 
                        public void run() { 
                            try { 
                                // Displaying the thread that is running 
                                System.out.println ("Thread " + Thread.currentThread().getId() + " is running"); 
                      
                            } 
                            catch (Exception e) { 
                                // Throwing an exception 
                                System.out.println ("Exception is caught"); 
                            } 
                        } 
                    } 
                      
                    // Main Class 
                    public class Multithread { 
                        public static void main(String[] args) { 
                            int n = 8; // Number of threads 
                            for (int i=0; i<8; i++) { 
                                MultithreadingDemo object = new MultithreadingDemo(); 
                                object.start(); 
                            } 
                        } 
                    } 

                    /* Output
                    Thread 8 is running
                    Thread 9 is running
                    Thread 10 is running
                    Thread 11 is running
                    Thread 12 is running
                    Thread 13 is running
                    Thread 14 is running
                    Thread 15 is running */
            
                    // Java code for thread creation by implementing the Runnable Interface 
                    class MultithreadingDemo implements Runnable { 
                        public void run() { 
                            try { 
                                // Displaying the thread that is running 
                                System.out.println ("Thread " + Thread.currentThread().getId() + " is running"); 
                      
                            } 
                            catch (Exception e) { 
                                // Throwing an exception 
                                System.out.println ("Exception is caught"); 
                            } 
                        } 
                    } 
                      
                    // Main Class 
                    class Multithread { 
                        public static void main(String[] args) { 
                            int n = 8; // Number of threads 
                            for (int i=0; i<8; i++) { 
                                Thread object = new Thread(new MultithreadingDemo()); 
                                object.start(); 
                            } 
                        } 
                    } 
            
                    // Only one thread can execute at a time. 
                    // sync_object is a reference to an object
                    // whose lock associates with the monitor. 
                    // The code is said to be synchronized on
                    // the monitor object
                    synchronized(sync_object) {
                       // Access shared variables and other
                       // shared resources
                    }
            
Difference between synchronized block and method
Main difference between synchronized method and synchronized block is selection of lock on which critical section is locked.
Volatile
wait(), notify(), notifyAll()
Java Multithreading Questions: