You can define an abstract method to be protected, and hence not part of the public API of the class. However, that seems like an odd design.

Another thing – instance variables. You can have inheritable instance variables in the abstract class.

Abstract class Methods can be defined at various levels down the path.

In a 100% abstract class, you can also define non constant variables that can be herited. It is not possible with interfaces.

The one case where an “100% abstract class” may be advantageous over an interface is in places where API stability is a key concern.

If you write an API where other people are expected to implement your interface you have to stick to the interface. You can’t add any methods to the interface later on because that would break all clients (you would have to work around this by implement a second interface and let your code check againt the usage with instanceof checks and provide an fallback).

Simple Thread implementing Runnable
Counter.java

public class Counter implements Runnable{
    public void run(){
        System.out.println("I am Counter Run Method");
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Counter objCounter = new Counter();
        Thread objThread = new Thread(objCounter);
        objThread.start();
    }
}
I am Counter Run Method

Main.java(Using Lambda Expression)

public class Main {
    public static void main(String[] args) {
        Thread objThread = new Thread(() -> {
            System.out.println("I am lambda Counter method");
        });

        objThread.start();
    }
}
I am lambda Counter method

new vs runnable vs terminated

  1. When you create thread using new Operator it would be in “new” state
  2. Once you call start method over thread it would Transend to “runnable” state
  3. When run method completed execution it would Transend to “terminated” state

start() vs run()
Thread can be invoked using start or run method. If you use the myThread.start() method it initiates execution of new thread, jvm takes care of execution and scheduling of run method in separate concurrent context. Calling the run method directly myThread.run() will not start a new thread; it will execute the run method in the current thread (ie main thread).

start method of thread class is implemented as when it is called a new Thread is created and code inside run() method is executed in that new Thread. While if run method is executed directly than no new Thread is created and code inside run() will execute on current Thread and no multi-threading will take place

public class Main {
    public static void main(String[] args) {
        Thread objThread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
        });

        objThread.start();
    }
}

Output

Thread-0
public class Main {
    public static void main(String[] args) {
        Thread objThread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
        });

        objThread.run();
    }
}

Output

main
  1. start() – Initiates the execution of the thread, causing the run method to be called. When you call the start() new thread would spawn and start execution other than main thread

    Task.java

    public class Task implements Runnable{
        @Override
        public void run() {
            System.out.println("Hello from Task.class, executed by " + currentThread().getName() + " thread");
        }
    }
    

    Main.java

    public class Main {
        public static void main(String[] args) {
            Thread thread = new Thread(new Task());
            thread.start();
            thread.run();
        }
    }
    

    Output

    Hello from Task.class, executed by main thread
    Hello from Task.class, executed by Thread-0 thread
    
  2. run() – Contains the code that will be executed by the thread. This method needs to be overridden when extending the Thread class or implementing the Runnable interface. Usage: Defined by the user based on the specific task.
  3. sleep(long milliseconds) – Causes the thread to sleep for the specified number of milliseconds, pausing its execution.
    Thread.sleep(1000);
    
  4. join() Waits for the thread to complete its execution before the current thread continues. It is often used for synchronization between threads.
    myThread.join();
  5. interrupt() Interrupts the thread, causing it to stop or throw an InterruptedException. The thread must handle interruptions appropriately.
    myThread.interrupt();
    
  6. isAlive() Returns true if the thread has been started and has not yet completed its execution, otherwise returns false.
    boolean alive = myThread.isAlive();
    
  7. setName(String name) Sets the name of the thread.
    myThread.setName("MyThread");
    
  8. getName() Returns the name of the thread.
    String threadName = myThread.getName();
    
  9. getName() Returns the name of the thread.
    String threadName = myThread.getName();
    
  10. setPriority(int priority) Sets the priority of the thread. Priorities range from Thread.MIN_PRIORITY to Thread.MAX_PRIORITY.
    myThread.setPriority(Thread.MAX_PRIORITY);
    
  11. getPriority() Returns the priority of the thread.
    int priority = myThread.getPriority();
    
  12. currentThread() Returns a reference to the currently executing thread object.
    Thread currentThread = Thread.currentThread();
    

Thread Implementation Using Runnable Interface

public class Threads2 implements Runnable 
{	
	public static void main(String[] args) 
	{
		Threads2 objThreads2 = new Threads2();
		Thread t1 = new Thread(new Threads2());
		t1.start();
	}
	
	public void run() 
	{	
		System.out.println("Thread Started");
		
		for(int i=0;i<=5;i++)
		{
			System.out.println(i);
			
			try 
			{
			  Thread.sleep(1000);
			}
			catch (InterruptedException e) 
			{
			  e.printStackTrace();
			}
		}
		
		System.out.println("Thread Stopped");
	}
}

There are Four Constructors we can use in Runnable Method of Implementation of Threads.
Thread() – Calls Thread Version of run Method
Thread(Runnable Target)
Thread(Runnable Target, String Name)
Thread(String Name)

If we dont Pass the Instance of Class To thread Constrctor then it will call its own Run Method

Thread t = new Thread(new MyThread());
/**
 * Anonymous Inner Classes
 */
public class Outer7 
{	
	public static void main(String[] args) 
	{
		Outer8 objOuter8 = new Outer8();
		objOuter8.act();
	}
	
	public void eat()
	{
		System.out.println("I am Eat Method");
	}
}

class Outer8 extends Outer7
{
	Outer7 objOuter7 = new Outer7(){
		public void eat()
		{
			System.out.println("I am Overridden Eat Method");
		}	
	};
	
	public void act()
	{
		objOuter7.eat();
	}
}

Output

I am Overridden Eat Method
/**
 * Referencing Method-Local Inner Class
 */
public class Outer6 
{	
	private static int x = 25;
	
	public static void main(String[] args) 
	{	
		invokeInnerClass();
	}
	
	public static void invokeInnerClass()
	{	
	   class Inner6
	   {	
		 public void displayInnerMsg()
		 {
		   System.out.println(x);
		   System.out.println("I am a Inner Class");
		 }
	   }
		
		Inner6 objInner6 = new Inner6();
		objInner6.displayInnerMsg(); 
	}
}

Output

25
I am a Inner Class

The Inner Class Defined with in static method has access to only static variables defined in the outer class

 /**
 * Referencing Method-Local Inner Class
 */
public class Outer6 
{	
	public static void main(String[] args) 
	{
		Outer6 objOuter6 = new Outer6();
		objOuter6.invokeInnerClass();
	}
	
	public void invokeInnerClass()
	{
		class Inner6
		{
			public void displayInnerMsg()
			{
				System.out.println("I am a Inner Class");
			}
		}
		
		Inner6 objInner6 = new Inner6();
		objInner6.displayInnerMsg(); 
	}
}

Output

 I am a Inner Class

You cannot Access local variable of the Method since variables are stored in Stack and object exists in Heap memory.The Stack memory will be blown away once the Method exits.

You can access a variable marked as Private in Outer Class.

You can access local variable marked as Final.

The class inside Method-Local Inner class can be either abstract or final.Other private, public and protected are not allowed

/**
 * Referencing Outer Class Object and Its Value
 */
public class Outer5 
{	
	private int x = 7;
	
	public static void main(String[] args) 
	{
		Outer5 objOuter5 = new Outer5();
		objOuter5.callInnerClassMethod();
	}
	
	public void callInnerClassMethod()
	{
		Inner5 objInner5 = new Inner5();
		objInner5.InnerClassMethod();
	}
	
	public class Inner5
	{
		private int x = 5;
	
		public void InnerClassMethod()
		{
		 System.out.println(x);
		 System.out.println(Outer5.this.x);
		}
	}
}

Output

5
7
public class Outer1
{
	public static void main(String[] args) 
	{
		Outer2 objOuter1 = new Outer2();
		Outer2.Inner1 objInner1 = objOuter1.new Inner1();  
		objInner1.innerMethod1();
	}
}

class Outer2 
{	
	public void makeInner()
	{
		Inner1 objInner1 = new Inner1();
		objInner1.innerMethod1();
	}
	
	class Inner1
	{
		public void innerMethod1()
		{
			System.out.println("This is Inner Method1");
		}
	}
}

Output

This is Inner Method1
public class Outer1
{
	public static void main(String[] args) 
	{
		Outer2 objOuter1 = new Outer2();
		Outer2.Inner1 objInner1 = objOuter1.new Inner1();  
		objInner1.innerMethod1();
	}
}

class Outer2 
{	
	public void makeInner()
	{
		Inner1 objInner1 = new Inner1();
		objInner1.innerMethod1();
	}
	
	class Inner1
	{
		public void innerMethod1()
		{
			System.out.println("This is Inner Method1");
		}
	}
}

The equals method that comes along java.lang.Object provides an equal method which does the following

<pre>
public boolean equals(Object o)
{
if(this == 0) return true;
}
</pre>

But the above implementation only for Integer, Boolean, Character and Other Wrapper classes because it is overridden.

When we define our own class and define equals the below is how its going to be.

<pre>

class mac
{
int Age;
}
</pre>

Now the below code does not give any output until equals method is overridden if you comment out   objmac2 = objmac1;      .

<pre>
Integer num1 = new Integer(5);
Integer num2 = new Integer(5);

mac objmac1 = new mac();
mac objmac2 = new mac();

objmac2 = objmac1;

objmac1.Age = 25;
objmac2.Age = 25;

if(objmac1 == objmac2)
System.out.println(“They are same”);

if(objmac1.equals(objmac2))
System.out.println(“Objects are same”);

</pre>

 

 

 

 

 

 

What is Node?

  1. Node is not a programming language rather runtime environment to run Javascript code
  2. Browsers provide runtime environment to run javascript.Node uses Chrome v8 engine internally to run js code.
  3. In Traditional server request are assigned a thread and the response would be server. So there exist one thread for each request.The threads cannot be shared and Blocking and Synchronous in nature
  4. In node there is single thread and all these request would be served by this single thread hence its is Nonblocking and Asynchronous in nature.
  5. Because of this asynchronous nature node is not suitable for Data intensive operations and for image manipulation, Since the threads would be locked for a long time
  6. Since node application runs in an environment outside broswer it provides file handling operations which are not possible by browsers.

How the Execution of js files in Node happens

  1. Node variables has 2 scopes –
    • Global Scope
    • Local Scope or Module Scope
  2. Variables like Window, Console is global scope as they are accessed globally over broswer
  3. In Node everything is a module. Each js file would be accounted for as a module. The js file execution happens within its own module scope.
  4. The below statements are same in node
      console.log('Uses console without global prefix');
      global.console.log('Uses console with global prefix');
     

    Output

    Uses console without global prefix
    Uses console with global prefix
    
  5. Let’s try to print the module variable in Node js using below code.The code below prints the details of the module such as js file name, exports done from module and so on.
      console.log(module); 
     

    Output

    Module {
      id: '.',
      exports: {},
      parent: null,
      filename: 'D:\\AngularProjects\\NodeServer\\index.js',
      loaded: false,
      children: [],
      paths:
       [ 'D:\\AngularProjects\\NodeServer\\node_modules',
         'D:\\AngularProjects\\node_modules',
         'D:\\node_modules' ] }
    
  6. Exporting Variable and Function From Module
    We exported a variable and a function from logger.js and we called the same in index.js.Now when you run console.log(module) we can see the exported functionality in exports
    logger.js

    var log = "Log Me"
    
    function getLoggedValue(message){
        console.log(message);
    }
    
    module.exports.log=log;
    module.exports.printLog=getLoggedValue;
     

    index.js

    const logger = require('./logger');
    console.log(logger.log);
    logger.printLog('Hi there');
    

    Output

    Log Me
    Hi there
    

    You can see what is imported simply by using below statement in index.js
    index.js

    const logger = require('./logger');
    console.log(logger);
    

    Output

    { log: 'Log Me', printLog: [Function: getLoggedValue] }
    
  7. In case you are having just a single function the same thing can be accessed in the imported js as below. Let export just a single function in logger.js
  8. logger.js

    var log = "Log Me"
    
    function getLoggedValue(message){
        console.log(message);
    }
    
    module.exports=getLoggedValue;
    

    index.js

    const logger = require('./logger');
    logger('Hi there');
    

    Output

    Hi there
    
  9. Node always executes modules inside immediately invokable function expression.It is called Module Wrapper Function
    (function(exports, require, module, __filename, __dirname) {
    // Module code actually lives in here
    });
    

    Before a module’s code is executed, Node.js will wrap it with a function wrapper that looks like the following:
    By doing this, Node.js achieves a few things:It keeps top-level variables (defined with var, const or let) scoped to the module rather than the global object.
    It helps to provide some global-looking variables that are actually specific to the module. The module and exports objects that the implementor can use to export values from the module.The convenience variables __filename and __dirname, containing the module’s absolute filename and directory path.

Modules in Node
Node is a combination of different modules we interact with based on our needs. Below are a few of them as listed.

  1. Path – Using path we are listing the details of the filename
  2. OS – We check for the total memory and free memory
  3. File – We list the files in the directory.Always use asynchrounous reading mode(fs.readdir) for file instead of (fs.readFileSync).
  4. Events
  5. Http

index.js

console.log('-------Path module-------');
const path = require('path');
var pathObj = path.parse(__filename);
console.log(pathObj);

console.log('------OS module--------');
const os = require('os');
var totalMem = os.totalmem();
var freeMem = os.freemem();
console.log(`Total Memory -  ${totalMem}`);
console.log(`Free Memory -  ${freeMem}`);

console.log('------FS Module--------');
const fs = require('fs');
fs.readdir('./', (err, files)=>{
    if(err)
     console.log('Error', err);
    else 
     console.log('Files', files);
});

Output

-------Path module-------
{ root: 'D:\\',
  dir: 'D:\\AngularProjects\\NodeServer',
  base: 'index.js',
  ext: '.js',
  name: 'index' }

------OS module--------
Total Memory -  8465264640
Free Memory -  1929568256

------FS Module--------
Files [ 'index.js', 'logger.js', 'package-lock.json', 'test.html' ]

Event Module
Event is a singnal which tells something has happened.Below is a simple code for event listener

  1. We acquire handle of event class using require in EventEmitter
  2. Create object using new for EventEmitter
  3. Add the event to listener and define a function which needs to be called when the event gets fired
  4. Adding the event could be done using addListener and also by using on method
  5. Emit the event using emit methid

index.js

const EventEmitter = require('events');
const emitter = new EventEmitter();

emitter.addListener('Message Listener', ()=>console.log('Listener Called'));
emitter.emit('Message Listener');

Output

Listener Called

Lets try to pass arguments to event listener. Arguments should always be passed as JSON Objects as as one parameter inorder to avoid confusion though passing as a individual argument is going to work fine.
index.js

const EventEmitter = require('events');
const emitter = new EventEmitter();

emitter.addListener('Message Listener', (argObj)=>{
                                                    console.log(argObj.argument1);
                                                    console.log(argObj.argument2);
                                                  });
emitter.emit('Message Listener', {'argument1':'arg1 val', 'argument2':'arg2 val'});

Output

arg1 val
arg2 val

Now let’s build a custom class which does the logging

  1. We have a logger.js which is a utility class with log method in it
  2. We call the log method from eventList class by importing the Logger Class
  3. In the logger we extend event emitter and use this reference to call the eventEmitter

logger.js

const EventEmitter = require('events');

class Logger extends EventEmitter
{
    log(strLogMessage)
    {
        this.emit('MessageListener', strLogMessage);        
    }
}

module.exports = Logger;

eventList.js

const Logger = require('./logger');

const objLogger = new Logger(); 

objLogger.addListener('MessageListener', (arg) =>{console.log(arg)});
objLogger.log('Calling the Log Method');

Output

Calling the Log Method

HTTP Module
server.js

const http = require('http');

const server = http.createServer();

const server = http.createServer((req, res)=>{
    if(req.url === '/')
    {
        res.write('Hello World...');
        res.end();
    }

    if(req.url === '/api/customers')
    {
        res.write(JSON.stringify(['Customer1', 'Customer2', 'Customer3']));
        res.end();
    }
});

server.listen(3000);
console.log('Listening on Port 3000.....');

Input and Output

IP : http://localhost:3000/
OP : Hello World...

IP : http://localhost:3000/api/customers
OP : ["Customer1","Customer2","Customer3"]