Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Monday, June 27, 2022

Hard things in Computer Science and in Software Development

 Hard things in Computer Science and Development

Image


If you’ve more than a couple of years of experience in IT, you probably have stumbled upon the following quote:

There are only two hard things in computer science: cache invalidation and naming things.

— Phil Karlton

Then, because it’s such a great quote, it evolved:

However, I think that the initial quote is misleading. A lot of things are hard in computer science. This post aims to describe some of them.

Cache invalidation

I had a few use-cases for caching in my professional career. When I did, it was mostly to cache Hibernate entities. Only once did I implement my own cache. I used a simple HashMap as it was for a batch job as the cache size was small: no invalidation was needed.

Most cache implementations implement the Cache-Aside strategy. In Cache-Aside, the application tries to load data from the cache. If the cache has them, it returns them; if not, the application reads from the source of truth - in general, a database.

While data are stored in the cache, they may change in the database. In short, the probability that data in the cache and the source of truth diverge increases as time passes. For this reason, we sometimes need to synchronize data with the source of truth. It’s achieved by cleaning data from the cache - cache invalidation, also known as TTL.

The TTL specifies how long an entry is valid. After the time has elapsed, the cache removes it, and the next read will load data from the source of truth.

The tricky thing, in this case, is to choose the correct TTL:

If the reference data in the source of truth changes before invalidation, clients read stale data

If the invalidation happens before the change, an unnecessary reload happens.

In essence, the smaller the TTL, the less chance to read stale data, but the less useful is the cache.

Naming things

If you have any experience as a developer, you probably are convinced that naming things is challenging indeed. If not, let’s introduce another quote:

Programs are meant to be read by humans and only incidentally for computers to execute

— Donald Knuth

Here’s another one, slightly more inflammatory:

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

— Martin Fowler

For example, here’s some code:

data class Foo(val bar: String)

class Baz : IllegalArgumentException()

data class Qux(val quux: Double, val foo: Foo) {

    operator fun plus(qux: Qux) =

        if (foo != qux.foo) throw Baz()

        else Qux(quux + qux.quux, foo)

}

data class Currency(val symbol: String)

class MismatchCurrencyException : IllegalArgumentException()

data class Amount(val number: Double, val currency: Currency) {

    operator fun plus(amount: Amount) =

        if (currency != amount.currency) throw MismatchCurrencyException()

        else Amount(number + amount.number, currency)

    }

}


Thanks to the usage of APIs, namely IllegalArgumentException and plus(), you may infer somewhat what the code does. However, correctly renaming classes and fields reveals our intent:

data class Currency(val symbol: String)

class MismatchCurrencyException : IllegalArgumentException()

data class Amount(val number: Double, val currency: Currency) {

    operator fun plus(amount: Amount) =

        if (currency != amount.currency) throw MismatchCurrencyException()

        else Amount(number + amount.number, currency)

    }

}

When I worked on projects, I always cautioned about the following issues when talking with the business:

Using different words to cover the same reality

Using the same word to cover different realities

The second is much worse, as you may think you’re talking about the same thing with the business or fellow developers, but you’re not. If the talk ends in agreement, but each party has a different reality in their head, it’s a recipe for a future disaster.

Within the scope of verbal communication, it’s possible to ask questions about the meaning of such and such words. In code, it’s not! Hence, naming classes and variables must convey the exact meaning.

It’s hard because you need to be precise without being verbose.

Dates, times, and timezones

I already wrote about Date and time gotchas. To sum up:

The move from the Julian calendar to the Gregorian one happened at different dates depending on the country involved

Some countries' timezone are not entirely congruent to their geographical location

Some countries implement DST, some not. Even worse, some did and don’t anymore.

Countries sometimes change their timezones. While it’s not frequent, it happens more frequently than most think.

Not all timezones are separated by one hour. For example, India is UTC+5:30, but three timezones are spaced by 45 minutes.

Estimates

Estimates in software development projects are so hard to get right that some people working on the development side started the "No Estimate" movement. I won’t delve into the pros and cons of not doing estimates; my point is just that estimating a non-trivial software project is challenging.

I think that entire books have been written on the reasons why estimates are hard and how to improve them. Let’s summarize the reasons:

Not only software projects

Many who are involved in software projects but do not know how they work are eager to compare the activity with house building. Unfortunately, "house" can encompass different levels of industrialization. What the people refer to is an off-the-shelf building. It involves low or zero customization. Software development projects are on the opposite side of the scale, akin to unique architectural chef-d’oeuvre. For a more detailed explanation, look at the following On house building and software development projects post.

Problems along the way

Estimates are provided before the start of the project, with all parameters available at the time. Unfortunately, while risk management accounts for the known knowns and the known unknowns, it’s impossible to forecast the unknown unknowns. With the highly-mutable state of software projects, it’s practically a given that something unexpected happens, invalidating our previous estimates.

The nature of estimates

By definition, an estimate is a guess. The problem is that most treat them as a deadline. At this point, the organization will focus on respecting the deadline, regardless of the trade-offs - a recipe for failure.

Distributed systems

There’s so much one can do with a single computer, even a multicore one. Adding more resources to a computer rapidly hits the point of diminishing returns. You can do nothing at this point but distribute the load across several computers. Welcome to the realm of distributed systems!

The problem with distributed systems is that they are easy "to get wrong". Here is the list of fallacies regarding distributed systems:

The network is reliable

Latency is zero

Bandwidth is infinite

The network is secure

Topology doesn’t change

There is one administrator

Transport cost is zero

The network is homogeneous.

Tons of books and theses have been written on distributed systems. People who can get them right deserve all my respect.

In my career, I stumbled upon two distributed systems problems:

Dual writes

Leader election

Dual writes

Imagine a system with two distributed data stores. We require that they must contain the same data.

It qualifies as the dual write problem. In a single database, we can solve it with database transactions. In two different databases, two-phase commits are available, even if they might not be reliable. If the stores that you need to write to cannot be enrolled in 2PC, as in microservices architectures, you need to rely on compensating transactions. Compensating transactions are fragile and complex to implement correctly, if at all.

From a theoretical point of view, the CAP teaches us that we can choose only two out of three capabilities: Consistency, Availability, and Partition tolerance. In reality, the choice is no choice at all. Because the system is distributed, we need to choose P; because modern requirements forbid us to block, we need to choose A. The trade-off is consistency: both stores will converge to the same state over time.

While working on this problem, I discovered Change-Data-Capture. The idea behind CDC is to send updates to a single store and stream the diffs of the new state to the other one. To implement it by oneself is not trivial. I’d recommend using an existing product: I’ve used Debezium successfully in the past for my demos.

Leader election

Distributed systems rely on multiple nodes, and coordination across them is mandatory. Some rely on a specific node referred to as the leader to manage other nodes, while others are leaderless.

Most modern implementations are leader-based: it seems leaderless implementations are less reliable, though, truth to be told, I cannot tell the reason given the depth of my current understanding at the moment of this writing). Such implementations require all nodes to agree on which node is the leader among them - consensus. When a network partition happens, some nodes cannot communicate with others. It’s relatively easy to reach a consensus in a partition; it’s more challenging when the network reunites, and a single leader must be selected among all previous ones.

It’s why the Paxos algorithm, or the Paxos family of algorithms, was invented. However, experts seem to think that Paxos is error-prone to implement: the Raft algorithm is an attractive easier-to-implement alternative. In any case, easier doesn’t mean easy.

Proving code is bug-free

Traditional software engineering mandates testing to avoid bugs. Unfortunately, whatever approach you favor - unit, integration, end-to-end, or a mix of the three - doesn’t guarantee your code has no bugs. It’s, in fact, quite widespread to find bugs in production despite the infamous 100% code coverage. The only reliable way to have bug-free code is to prove it. It requires solid mathematical foundations and a programming language that allows formal proofs.

A couple of such languages exist. Unfortunately, all of them still belong to academia; the ones I’ve heard of are Coq, Idris, and Isabelle.

Until any of them makes it into the mainstream industry, writing bug-free code will be part of one the hard things in computer science.

Summary

Writing there are only two hard things in computer science is a strong claim. In this post, I tried to list several hard things I’ve been exposed to during my career. I believe there are many others: I’ll be interested in the ones you’ve encountered.



Wednesday, June 29, 2016

Reverse an array without affecting special characters in Java

Simple Solution:
1) Create a temporary character array say temp[].
2) Copy alphabetic characters from given array to temp[].
3) Reverse temp[] using standard string reversal algo.
4) Now traverse input string and temp in a single loop. Wherever there is alphabetic character is input string, replace it with current character of temp[].

Efficient Solution:
Time complexity of above solution is O(n), but it requires extra space and it does two traversals of input string.
We can reverse with one traversal and without extra space. Below is algorithm.

Solution 1:

public class ReverseArrayWithoutSpecial
{
   public static void main(String[] args)
   {
     System.out.println(reverseString("man ish#"));
   }
   public static String reverseString(String input)
   {
     char[] inputArr = input.toCharArray();
     char[] tempArr = new char[input.length()];
     int i=0;
     int j=0;
     for (char ch:inputArr)
     {
       if(Character.isAlphabetic(ch))
       {
         tempArr[i] = ch;
         i++;
       }
     }
     i--;
     while(j<i)
     {
       char temp = tempArr[i];
       tempArr[i]= tempArr[j];
       tempArr[j]=temp;
       j++;
       i--;
     }
     for(i=0,j=0;i<input.length();i++)
     {
       if(Character.isAlphabetic(inputArr[i]))
       {
         inputArr[i]= tempArr[j++];
       }
     }
     return new String(inputArr);
   }
 }

Result: hsi nam#


Solution 2:

public class ReverseArrayWithoutSpecial
{
   public static void main(String[] args)
   {
     System.out.println(reverseString("a,b$c"));
   }
   public static String reverseString(String input) {
    char[] inputArr = input.toCharArray();
    int l = 0;
    int r = inputArr.length - 1;
    while (l < r) {
      if (!Character.isAlphabetic(inputArr[l])) {
        l++;
      } else if (!Character.isAlphabetic(inputArr[r])) {
        r--;
      } else {
        char tempChar = inputArr[l];
        inputArr[l] = inputArr[r];
        inputArr[r] = tempChar;
        l++;
        r--;
      }
    }
    return new String(inputArr);
  }

 }

Result: c,b$a


Tuesday, June 28, 2016

Applications of Depth First Search and Breadth First Traversal

Applications of Depth First Search

Depth-first search (DFS) is an algorithm (or technique) for traversing a graph.

Following are the problems that use DFS as a building block.

1) For an unweighted graph, DFS traversal of the graph produces the minimum spanning tree and all pair shortest path tree.

2) Detecting cycle in a graph 
A graph has cycle if and only if we see a back edge during DFS. So we can run DFS for the graph and check for back edges.

3) Path Finding

We can specialize the DFS algorithm to find a path between two given vertices u and z.

i) Call DFS(G, u) with u as the start vertex.
ii) Use a stack S to keep track of the path between the start vertex and the current vertex.
iii) As soon as destination vertex z is encountered, return the path as the
contents of the stack

4) Topological Sorting

Topological Sorting is mainly used for scheduling jobs from the given dependencies among jobs. In computer science, applications of this type arise in instruction scheduling, ordering of formula cell evaluation when recomputing formula values in spreadsheets, logic synthesis, determining the order of compilation tasks to perform in makefiles, data serialization, and resolving symbol dependencies in linkers [2].

5) To test if a graph is bipartite

We can augment either BFS or DFS when we first discover a new vertex, color it opposited its parents, and for each other edge, check it doesn’t link two vertices of the same color. The first vertex in any connected component can be red or black.

6) Finding Strongly Connected Components of a graph A directed graph is called strongly connected if there is a path from each vertex in the graph to every other vertex.

7) Solving puzzles with only one solution, such as mazes. (DFS can be adapted to find all solutions to a maze by only including nodes on the current path in the visited set.)


Applications of Breadth First Traversal

We have earlier discussed Breadth First Traversal Algorithm for Graphs. We have also discussed Applications of Depth First Traversal. In this article, applications of Breadth First Search are discussed.

1) Shortest Path and Minimum Spanning Tree for unweighted graph In unweighted graph, the shortest path is the path with least number of edges. With Breadth First, we always reach a vertex from given source using minimum number of edges. Also, in case of unweighted graphs, any spanning tree is Minimum Spanning Tree and we can use either Depth or Breadth first traversal for finding a spanning tree.

2) Peer to Peer Networks. In Peer to Peer Networks like BitTorrent, Breadth First Search is used to find all neighbor nodes.

3) Crawlers in Search Engines: Crawlers build index using Bread First. The idea is to start from source page and follow all links from source and keep doing same. Depth First Traversal can also be used for crawlers, but the advantage with Breadth First Traversal is, depth or levels of built tree can be limited.

4) Social Networking Websites: In social networks, we can find people within a given distance ‘k’ from a person using Breadth First Search till ‘k’ levels.

5) GPS Navigation systems: Breadth First Search is used to find all neighboring locations.

6) Broadcasting in Network: In networks, a broadcasted packet follows Breadth First Search to reach all nodes.

7) In Garbage Collection: Breadth First Search is used in copying garbage collection using Cheney’s algorithm. Refer this and for details. Breadth First Search is preferred over Depth First Search because of better locality of reference:

8) Cycle detection in undirected graph: In undirected graphs, either Breadth First Search or Depth First Search can be used to detect cycle. In directed graph, only depth first search can be used.

9) Ford–Fulkerson algorithm In Ford-Fulkerson algorithm, we can either use Breadth First or Depth First Traversal to find the maximum flow. Breadth First Traversal is preferred as it reduces worst case time complexity to O(VE2).

10) To test if a graph is Bipartite We can either use Breadth First or Depth First Traversal.

11) Path Finding We can either use Breadth First or Depth First Traversal to find if there is a path between two vertices.

12) Finding all nodes within one connected component: We can either use Breadth First or Depth First Traversal to find all nodes reachable from a given node.

Many algorithms like Prim’s Minimum Spanning Tree and Dijkstra’s Single Source Shortest Path use structure similar to Breadth First Search.

There can be many more applications as Breadth First Search is one of the core algorithm for Graphs.

Monday, June 27, 2016

Methods in Java

Methods in Java

A method represents a group of statements that performs a task.Methods has two parts.

  1. Method Header or Method Prototype
  2. Method Body
Method Header: 

it contains method name,method parameters and method return data type.Method Prototype written in forms:

return datatype methodName(parameter 1,parameter 2);

Method Body:

Below the method header,we should write the method body .Method body consists of a group of statement which can perform the tasks.

{
  statements;
}

Understanding Methods

Lets take an example:


/**
 * 
 */
package com.myobjectrelation;

/**
 * @author Abhinaw.Tripathi
 *
 */
class Sample
{
  private double num1,num2;
  
  public Sample(double x,double y)
  {
this.num1=x;
this.num2=y;
  }
  
  void sum()
  {
 double res=num1+num2;
 System.out.println("Sum is " + res);
  }

}

public class MethodExample 
{
public static void main(String[] args) 
{
Sample s=new Sample(10, 22.50);
s.sum();
}
}

Result:

Sum is 32.5

What is instance methods?

Ans: Instance methods are the methods which act on the instance variables of the class.To call the instance methods,we should use the form : objectname.methodName() .

Sample Program:

/**
 * 
 */
package com.myobjectrelation;

/**
 * @author Abhinaw.Tripathi
 *
 */
class Sample
{
  private double num1,num2;
  
  public Sample(double x,double y)
  {
this.num1=x;
this.num2=y;
  }
  
  void sum()
  {
 double res=num1+num2;
 System.out.println("Sum is " + res);
  }

}

public class MethodExample 
{
public static void main(String[] args) 
{
Sample s=new Sample(10, 22.50);
s.sum();
}
}

Result:
Sum is 32.5

What is static method?
Ans: Static method are the methods which do not act upon the instance variables of a class.Static methods are declared as 'Static' .

So to call the static methods ,we need not to create an object.we can call a static method.

Sample:

/**
 * 
 */
package com.myobjectrelation;

/**
 * @author Abhinaw.Tripathi
 *
 */

class Sample
{
static double sum(double num1,double num2)
{
double res=num1+num2;
return res;
}
}

public class StaticSample 
{
public static void main(String[] args)
{
      double x=Sample.sum(10, 20);
      System.out.println("Sum will be "+ x);
}

}

Result:

Sum will be 30.0

Static Methods:

A static method is a method that does not act upon instance variable of a class.The reason why static methods can not act on instance variables is that the JVM first executes the static  methods and then only it creates the objects .Since the objects are not available at the time of calling the static methods,instance variables are also not available. 

What is the difference between the instance variables and class variables(Static variables)?.
Ans: 
  • An instance variables is a variables whose separate copy is available to each object.A class variables is a variable whose single copy in memory is shared by all objects.
  • Instance variables are created in the objects on heap memory.Class variables are stored on method area.
Why instance variables are not available to static methods?

Ans: After  executing static methods,JVM creates the objects.So the instance variables of the objects are not available to static methods.

So, the execution sequence of JVM is the process where JVM executes first of all any static blocks in the java program.then it executes static methods and then it creates any objects needed by the program.Finally,it executes the instance methods.


Static Block

A Static block is a block of statements declared as static .
                             static {
                                statements;
                             }

JVM executes a static block on highest priority basis.This means JVM first goes to static block even before it looks for the main() method in the program.This can be understood from the below program.

Program:
 package com.myobjectrelation;

/**
 * @author Abhinaw.Tripathi
 *
 */
public class TestSample 
{
static 
{
System.out.println("Static block");
}
public static void main(String[] args) 
{
System.out.println("Static method");
}
}

Result:

Static block
Static method

Is it possible to compile and run a java program without writing main() method?
Ans: Yes,it is possible by using static block in the java program.


The keyword 'this'

this is a keyword that refers to the object of the class where it is used.In other words,this refers to the object of the present class.Generally,we write instance variables,constructor and methods in a class.All these members are referenced by this.
When an object is created to a class,a default reference is also created internally to the object.This default reference is nothing but this .

Sample: 

/**
 * 
 */
package com.myobjectrelation;

/**
 * @author Abhinaw.Tripathi
 *
 */

class TestSampleDemo
{
  private int x;
  public TestSampleDemo() 
  {
this(55);
this.access();
}
 
  TestSampleDemo(int x)
  {
  this.x=x;
  }
 
  void access()
  {
  System.out.println("x=" + x);
  }
}

public class ThisKeywordRef
{
public static void main(String[] args) 
{
TestSampleDemo s=new TestSampleDemo();
 
      s.access();
}

}

Result:

x=55
x=55

Instance Methods

Instance methods are methods which act upon the instance variables.To call the instance methods,objects is needed,since the instance variables are contained in the object.The speciality of instance method is that they can access not only the instance variables but also the static variables directly.

They are of two types.
  1. Accessor methods - this method simply access or read the instance variables.they do not modify the instance variables.
  2. Mutator methods - this method not only access the instance variables but also modify them.
Program: 

/**
 * 
 */
package com.myobjectrelation;

/**
 * @author Abhinaw.Tripathi
 *
 */
class Person
{
 private String name;
 private int age;
public String getName() 
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge() 
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
}

public class AccessorMutatorApp
{
public static void main(String[] args)
{
Person p1=new Person();
p1.setAge(28);
p1.setName("Abhinaw");
System.out.println("Person name:" + p1.getName());
System.out.println("Person age: " +p1.getAge());

}

}

Result: 

Person name:Abhinaw
Person age: 28

Passing Primitive Data types to Methods

Primitive data types or fundamental data types represent single entities or single values.for example,
char,byte,short,int,long,float,double and boolean etc. because they store single values.They are passed to methods by value.this means when we pass primitive data types to a method, a copy of those will be passed to methods.therefore,any changes made to them inside the method will not affect them outside the method.
  • take a temporary variable temp.
  • preserve a copy of num1 into temp.
  • now store num2 into num1 .
  • store the previous copy of num1 from temp into num1.
Passing Objects to Methods

We can also pass class objects to methods, and return objects from the methods. for example,

        Employee myMethod(Employee obj)
         {
            statements;
            returned obj;
         }


Even the objects are also passed to methods by value.This means, when we send an object to a method,its bit by bit copy will be sent to the method.

How are objects are passed to methods in Java?

Ans: primitive data types ,objects ,even object references---every thing is passed to methods using 'pass by value' or 'call by value' concept.This means their bit by bit copy is passed to the methods.








Relationship Between Objects Java

Relationship Between Objects

It is possible to create objects for different classes and establish relationship between them.When the objects are related,it is possible to access and use members of one object in another object.When an object should start processing data where where another object has left.It is helpful to pass data from one object to another object in chained form.

There are three ways to relate objects in Java:


  1. Using References
  2. Using inner class concept
  3. Using inheritance
Relating Objects using References

Let us create two classes,One and Two . Suppose we want to access the members of class two in class one,we should relate their objects.we should relate their objects .for this just declare the reference variable of class two as an instance variable in class One. 

Program:


/**
 * 
 */
package com.myobjectrelation;

/**
 * @author Abhinaw.Tripathi
 *
 */

class One 
{
  int x;
  Two t;
  
  public One(Two t) 
  {
this.t=t;
x=10;
  }
  
  public void display()
  {
 System.out.println("One x= " + x);
 t.display();
 System.out.println("Two var="+t.y);
  }
  
}

class Two
{
 int y;
 public Two(int y)
 {
this.y=y;
 }
 void display()
 {
System.out.println("Two y= " +y);
 }
}

public class ObjectRelationUsingref
{
public static void main(String[] args) 
{
Two obj2=new Two(22);
One obj1=new One(obj2);
obj1.display();
}
}


Result:

One x= 10
Two y= 22
Two var=22


Another Sample Program:

/**
 * 
 */
package com.myobjectrelation;

/**
 * @author Abhinaw.Tripathi
 *
 */
class OneA
{
TwoB obj2;
public OneA(TwoB obj2)
{
  this.obj2=obj2;
}
double cube(double x)
{
double result=x*obj2.square(x);
return result;
}
}

class TwoB
{
Three obj3;
public TwoB(Three obj3) 
{
this.obj3=obj3;
}
double square(double x)
{
double result=x*obj3.get(x);
return result;
}
}

class Three
{

public double get(double x) 
{
return x;
}
 
}

public class Relate
{
public static void main(String[] args)
{
Three obj3=new Three();
TwoB obj2=new TwoB(obj3);
OneA obj1=new OneA(obj2);
double result=obj1.cube(5);
System.out.println("cube of 5 ="+result);
double result2=obj2.square(5);
System.out.println("square of 5 ="+result2);
}

}


Result:

cube of 5 =125.0
square of 5 =25.0


What is Object Graph?

Ans: Object graph is a graph showing relationship between different objects in memory.

Inner Class

Inner class is a class written within another class.Inner class is a basically a safety mechanism,since it is hidden from other classes in its outer class.

To make instance variables not available outside the class,we use private access specifier before the variables.this is how we provide the security mechanism to variables.Similarly,in some cases,we want to provide security for the entire class.in this case we use private access specifier before class.?.the problem is if we use private access specifier before a class ,the class is not available to the java compiler or JVM .So it is illegal to use private before a class name in java.

But private is allowed before an inner class and thus it is useful to provide security for the entire inner class because it is not available to other classes.This means an object to inner class can not be created in any other class.

Program:

/**
 * 
 */
package com.myobjectrelation;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author Abhinaw.Tripathi
 *
 */

class  BankAcct
{
 private double bal;
 public BankAcct(double b)
 {
this.bal=b;
 }
 void contact(double r) throws IOException
 {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter Password: ");
String password=br.readLine();
if(password.equals("abhinaw"))
{
Interest in=new Interest(r);
in.calculateInterest();
}
else
{
System.out.println("Sorry,you are not an authorized person");
return;
}
 }
 private class Interest
 {
private double rate;
     public Interest(double r) 
     {
this.rate=r;
}  
     
     void calculateInterest()
     {
    double interest=bal*rate/100;
    bal+=interest;
    System.out.println("updated Balance="+bal);
     }
 }
}

public class BankAccount
{
public static void main(String[] args) throws IOException
{
BankAcct account=new BankAcct(100000);
account.contact(9.5);
}

}

Result:

Enter Password: 
abhinaw
updated Balance=109500.0


Note: 

The inner class object will contain an additional field by the name this$0 which stores the reference number of the outer class object in memory.this is this$o is invisible field because reference of outer class object is available to inner class object,now inner class is able to refer to all the members of the outer class.
  1. An inner class is a safety mechanism .
  2. Inner class is hidden from other classes in its outer classes.
  3. An object to inner class can not be created into other classes.
  4. An object to inner class can be created only in its outer class.
  5. Inner class members can access the members of the outer class directly.
  6. Inner Class and Outer Class objects are created in separate memory locations.
  7. When same names are used, we can refer to outer class members in the inner class.
  8. Inner class decrease readability of a program.This is against the design principal of Java to be a simple programming language.

Anonymous Inner Class

It is an inner class without a name and for which only a single object is created.
Anonymous inner classes are very useful in writing implementation classes for listener interfaces in graphics programming or Android interfaces.Lets understand it by a simple program.

Program:

/**
 * 
 */
package com.myobjectrelation;

import java.awt.Button;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Abhinaw.Tripathi
 *
 */

class MyClass implements ActionListener
{

@Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
 
}

class But extends Frame
{
  public But() 
  {
Button btn=new Button();
add(btn);
btn.addActionListener(new MyClass());
  }
}

public class AnonymousListProg 
{

public static void main(String[] args)
{
But obj=new But();
obj.setSize(400,300);
obj.setVisible(true);

}

}


Result: A window will pop up and when you will click on it ,it will be gone.

  • MyClass is inner class inside But class.
  • The name MyClass is not written in its outer class i.e. But class.
  • MyClass object is created only once.
  • MyClass code is directly copied into the method parameter.

What is Anonymous Class?

Ans: It is an inner class whose name is not written in the outer class and for which only one object is created.

Another Example:

/**
 * 
 */
package com.myobjectrelation;

import java.awt.Button;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Abhinaw.Tripathi
 *
 */
public class AnotherAnonyExample extends Frame
{
public AnotherAnonyExample()
{
Button b=new Button();
add(b);
b.addActionListener(new ActionListener() 
{
@Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});  
}
public static void main(String[] args) 
{
But obj=new But();
obj.setSize(400, 300);
obj.setVisible(true);
}
}

Result: A window will pop up and when you will click on it ,it will be gone.

Note: Finally,anonymous inner class is helpful when we want to pass entire class code to a method,where the class name is not written but an object is created to it.

Another way of relating objects is inheritance which we have already discussed.

Inheritance Java Example

We can acquire all the members of a class and use them in another class by relating the objects of two class .This is possible by inheritance.

What is Inheritance?

Deriving new classes from existing classes such that the new classes acquire all the features of existing classes is called Inheritance.

So,inheritance is a concept where new classes can be produced from existing classes.the new created class acquires all the features of existing class from where it is derived.

Sample Program:

/**
 * @author Abhinaw.Tripathi
 *
 */
class Teacher
{
  int id;
  String name;
  String address;
  float sal;

  public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}

}

class Student
{
int id;
String name;
String address;
int marks;

 public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getMarks() {
return marks;
}
public void setMarks(int marks) {
this.marks = marks;
}

}

public class InheritanceApp
{
public static void main(String[] args)
{
Student s=new Student();
s.setName("Abhinaw");
s.setId(1001);
s.setAddress("Dlf Phase 1");
s.setMarks(50);

System.out.println("Student name="+s.getName());
System.out.println("Student Id="+s.getId());
System.out.println("Student address="+s.getAddress());
System.out.println("Student marks="+s.getMarks());
}


}


Result:

Student name=Abhinaw
Student Id=1001
Student address=Dlf Phase 1
Student marks=50

Another sample Program:

/**
 * @author Abhinaw.Tripathi
 *
 */
class Teacher
{
  int id;
  String name;
  String address;
  float sal;
  
  public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public float getSal() {
return sal;
}
public void setSal(float sal) {
this.sal = sal;
}

}

class Student extends Teacher
{
int marks;
public int getMarks()
{
return marks;
}
public void setMarks(int marks)
{
this.marks = marks;
}
}

public class InheritanceApp
{
public static void main(String[] args) 
{
Student s=new Student();
s.setName("Abhinaw");
s.setId(1001);
s.setAddress("Dlf Phase 1");
s.setMarks(50);
System.out.println("Student name="+s.getName());
System.out.println("Student Id="+s.getId());
System.out.println("Student address="+s.getAddress());
System.out.println("Student marks="+s.getMarks());
}

}

Result:

Student name=Abhinaw
Student Id=1001
Student address=Dlf Phase 1
Student marks=50

Why super class members are available to sub class?

Ans: Because,the sub class object contains a copy of super class object.then what is the advantage of inheritance?you can clearly see the second program was smaller than the first one.

The Keyword 'super'

If we create an object to super class ,we can access only the super class members, but not the sub class members. but if we create sub class object ,all the members of both super and sub class are available to it. This is the reason,we always create an object to sub class in inheritance.Some time the super class members and sub class members may have same names.In that case,by default only sub class members are accessible .

Sample Program:

/**
 * @author Abhinaw.Tripathi
 *
 */
class one
{
   int i=20;
   void show()
   {
  System.out.println("Super class Method:i " +i);
   }
}

class two extends one
{
int i=20;
void show()
  {
  System.out.println("Sub class Method: i" +i);
  } 
}

public class InheritanceSuperDemo 
{
public static void main(String[] args)
{
two t=new two();
t.show();
}

}

Result:

Sub class Method: i20

Another Sample Program using Super:

/**
 * @author Abhinaw.Tripathi
 *
 */
class one
{
   int i=20;
   void show()
   {
  System.out.println("Super class Method:i= " +i);
   }
}

class two extends one
{
int i=20;
void show()
  {
  System.out.println("Sub class Method: i" +i);
  super.show();
  System.out.println("super i= "+super.i);
  } 
}

public class InheritanceSuperDemo 
{
public static void main(String[] args)
{
two t=new two();
t.show();
}

}

Result:

Sub class Method: i20
Super class Method:i= 20
super i= 20

Another Sample Program using default constructor:

/**
 * @author Abhinaw.Tripathi
 *
 */
class one
{
   
   public one() 
   {
System.out.println("One");
   }
}

class two extends one
{
public two()
{
System.out.println("two");
}
}

public class InheritanceSuperDemo 
{
public static void main(String[] args)
{
two t=new two();
}

}

Result:

One
two

Another Program:

/**
 * @author Abhinaw.Tripathi
 *
 */
class one
{
   int i;
   
   public one(int a) 
   {
this.i=a;
   }
   
}

class two extends one
{
int i;
    public two(int a,int b)
    {
super(a);
i=b;
}
void show()
  {
  System.out.println("Sub class Method: " +i);
  System.out.println("super class i="+super.i);
  } 
}

public class InheritanceSuperDemo 
{
public static void main(String[] args)
{
 two t=new two(11, 12);
 t.show();
}

}

Result:

Sub class Method: 12
super class i=11


The Protected Specifier

The private members of the super class are not available to sub classes directly.But some times,there may be a need to access the data of super class in the sub class .For this purpose ,protected specifier is used.protected  is commonly used in super class to make the members of the super class available directly in its sub classes.We can think that the protected specifier works like public with respect to sub classes .

Sample Program:

/**
 *
 */
package com.inheritanceclass;

/**
 * @author Abhinaw.Tripathi
 *
 */
class Access
{
  private int a=10;
  protected int b=20;

}

class subClass extends Access
{
  public void get()
  {
//   /System.out.println(a); // error ---a is private
  System.out.println(b);
  }
}

public class ProtectedSpeInheritanceApp
{
/**
* @param args
*/
public static void main(String[] args)
{
 subClass sc=new subClass();
 sc.get();
}

}

Result:  20


Another Sample Program:

/**
 * 
 */
package com.inheritanceclass;

/**
 * @author Abhinaw.Tripathi
 *
 */
class Shape
{
 protected double l;
 
 public Shape(double l) 
 {
this.l=l;
 }
  
}

class Square extends Shape
{

public Square(double l) 
{
super(l);
}
void area()
{
System.out.println("Area of square:" + (l*l));
}
}


class Rectangle extends Square
{
    private double b;
public Rectangle(double x,double y) 
{
super(x);
b=y;
}
void calculateArea()
{
System.out.println("Area of rectangle = "+(l*b));
}
}

public class AnotherSampleProgInh
{

public static void main(String[] args)
{
      Square s=new Square(5.5);
      s.area();
      
      Rectangle rectngl=new Rectangle(5.5, 6);
      rectngl.calculateArea();
}
}

Result:

Area of square:30.25
Area of rectangle = 33.0

Types of Inheritance

There are two types of inheritance,Single and Multiple
  1. Single Inheritance: Producing sub classes from a single super class is called Single Inheritance.in this case,a single super class will be there.there can be one or more sub classes.     
  2. Multiple Inheritance: Producing sub classes from multiple super class is called Multiple Inheritance.in this case,there will be more than one super class and there can be one or more sub classes.
Note : In Java,only single inheritance is possible or you can say available.because multiple inheritance leads to confusion for the programmer.for example, class A has got a member x and class B has also got a member x. when another class C extends both the classes ,then there is a confusion regarding which copy of x is available in class C.





Friday, June 24, 2016

Polymorphism :

In java, a variable ,an object or a method can exist in different forms,thus performing
various task depending on the context.because same variable and method can perform different task.
So, the ability to exist in different forms is called Polymorphism.

Polymorphism with Variables:

When using variables ,some time inherently the data type of the result is decided by the
compiler  and accordingly execution proceeds.such as

int a=10,b=20;
System.out.println(a+b);

Thus the result a+b is exhibiting polymorphism nature.
So, Coercion is the automatic conversion between different data types done by the compiler.such as
 float a=15.5f;
 int x=(int)a;

What is conversion?

Ans: Conversion is an explicit change in the data type specified by the cast operator.

Polymorphism using Methods: 

if the same method performs different tasks, then that method is said  to exhibit polymorphism.

Types of Polymorphism:

-Static Polymorphism or Compile Time Polymorphism
-Dynamic Polymorphism or Run Time Polymorphism

Dynamic Polymorphism or Run Time Polymorphism:

The Polymorphism exhibited at run time is called Dynamic polymorphism. This means
when a method is called, the method call is bound to the method body at time of running
the program ,dynamically . In this case Java compiler does not know which method is called at the time of  compilation. Only JVM,s know at run time which method is to be executed .That is why it is called Run Time Polymorphism or Dynamic Polymorphism.

Sample  with two instance methods having same name:

    void add (int a ,int b)
{
System.out.println(" sum of two:" + (a+b));
}

void add (int a,int b,int c)
{
 System.out.println("sum of three :"+ (a+b+c);
}

The bodies are different So they can perform different tasks.
Now,who will decide which method to be executed?.is it Java compiler or JVM?.
Since, the methods are called by using an object ,the java compiler can not decide which method is actually called by user.It has to wait till the objects will be created at run time by JVM. So ,JVM will decide which methods would be get called.

Now,again there is a question how JVM knows which method would be called?.
Answer is for this JVM observes the signature of the methods.Methods signature consist of a method name and its parameter.then even if two methods have same name but their signature will be different.

What is method Signature?
Ans : Method signature represents the method name along with method parameters.
What happens is the JVM values passed to method at the time of method call with the method signature and picks up the appropriate method.

Sample Program:

class Sample
{
  void add (int a,int b)
  {
    System.out.println(" sum of two:" + (a+b));
  }

  void add (int a,int b,int c)
{
 System.out.println("sum of three :"+ (a+b+c);
}

}
 class PolyApp
 {
   public static void main(String args[])
   {
     Sample s=new Sample();
s.add(10,15);
s,add(10,15,20);
   }
 }

What is method Overloading?

Ans: Writing two or more methods in the same class in such a way that each method has same
 but with different method signatures---is called method overloading.

 What is method overriding?
 Ans: writing two or more methods in super and sub classes such that the methods have
 same name and same signature---is called method overriding.

 Sample Program:

 class One
 {
   void calculate (double x)
   {
     System.out.println("Square value = " + (x*x));
   }
 }

 class Two  extends One
 {
   void calculate (double x)
   {
     System.out.println("Cube value = " + (x*x*x));
   }
 }

 class OverridingApp
 {
   public static void main(String args[])
   {
     Two t=new Two();
t.calculate(22);
   }
 }

Note: 

when a super class method is overridden by the sub class method,JVM calls only the sub class
method and never the super class method.

What is the difference between Overloading and Overriding?

Method Overloading :

1) Writing two or more methods with same name but with different signature is called Method Overloading.

2)Method Overloading is done in the same class.

3)In method overloading ,method return type can be same or different.

Method Overriding : 

1) Writing two or more methods with the same name and same signature is called Method Overriding.

2)Method Overriding is done in super ans sub classes.

3)In method overriding ,methods return type should always be same.

Static Polymorphism :

The Polymorphism exhibited at compilation time is called Static Polymorphism.Here the java compiler knows without any ambiguity which method is called at the time of compilation.It is
called static polymorphism because at the time of compilation it needs not to wait till the
objects are created .Since at the time of the compilation ,the method call can be bound with actual method body,this comes under static polymorphism.

Polymorphism with Static Methods:

A static method  is a method whose single copy in memory is shared by all the objects of the class.static methods belong to the class rather than to the objects.So they are also called class
methods.When static methods are overloaded or overridden ,since they do not depend  on the objects,the java compiler need not wait till the objects are created to understand which method is called.

Sample Program:

class One
 {
   static void calculate (double x)
   {
     System.out.println("Square value = " + (x*x));
   }
 }

 class Two  extends One
 {
   static void calculate (double x)
   {
     System.out.println("Cube value = " + (x*x*x));
   }
 }

 class PolyApp
 {
   public static void main(String args[])
   {
     One o = new Two();
t.calculate(22);
   }
 }

 Result: 

 Square value = 484.0

Polymorphism with Private Methods :

Private methods are the methods which are declared by using the access specifier 'private'.this
access specifier makes the method not be available outside the class . So other programmers can
not access the private methods.even private methods are not available in the sub classes. This
means there is no possibility  to override the private methods of super class in its sub class.
So only method overloading is possible in case of private methods.

Can you override private methods?
Ans: No,private methods are not available in the sub classes,So they can not be overridden.

Polymorphism with Final Methods:

Methods which are declared as final are called final method.final method can not  be overridden
because they are not available to the sub class .So only method overloading is possible
with final method.


There are two uses of declaring a method as final which are
- when a method is declared as final,the performance will be better .
eg. In class A ,we got a final method, method1().This method is being called from class B method().

class A
{
  final void method1()
  {
    System.out.println("Hello");
  }
}

class B
{
  void method2()
  {
    A.method()1 ;
  }
}


Can we take private methods and final methods as same?

Ans: Yes, Java compiler assigns the value for the private methods at the time of compilation.
Also, private methods can not be modified at run time.this is the same class with final methods
also.Neither the private methods nor the final methods can be overridden.So private methods can be taken as final methods.


final Class:

A final class is a which is declared as final keyword before a class prevents inheritance.This
means sub class can not be created to a final class.

eg.  final class A
      class B extends A // invalid

What is final?
Ans: 
1)It is used to declare constants.
2)It is used to prevent inheritance.

What is difference between dynamic and static polymorphism?
Ans: 

Dynamic Polymorphism :

 It exhibited at run time.Here java compiler does not understand which methods is called at compilation time.Only JVM decides which method is called at run time.Method
overloading and Method Overriding using instance method are examples for dynamic polymorphism.

Static polymorphism: 

It exhibited at compile time.here java compiler knows which method is called.Method overloading and method overriding using static methods;method overloading using private of final methods are examples for static polymorphism.

Sample Program:

/**
 *
 */
package com.poly;

/**
 * @author Abhinaw.Tripathi
 *
 */
class Commercial
{

 private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

void calculateBill(int units)
{
System.out.println("Customer: " + getName());
System.out.println("Bill Amount: " + units *7.00);
}
}

class Domestic extends Commercial
{
void calculateBill(int units)
{
System.out.println("Customer: " + getName());
System.out.println("Bill Amount: " + units *2.50);
}
}

public class ElectricBillApp
{

public static void main(String[] args)
{
Commercial c=new Commercial();
c.setName("Abhinaw Tripathi");
c.calculateBill(250);

Domestic d=new Domestic();
d.setName("Sandeep");
d.calculateBill(100);

}

}

Result:

Customer: Abhinaw Tripathi
Bill Amount: 1750.0
Customer: Sandeep
Bill Amount: 250.0