What is Dependency Injection aka Inversion of control?
Let's understand first "coupling". When one class depends on another, they are called coupled.
Coupled class can't be tested in isolation. For example: Client depends on BookService, BookService depends on BookDAO, BookDAO depends on JdbcRepository.
class Client{
public static void main(String[] args){
Book book = new Book(1,"Effective Java","Joshua Bloch");
BookService service = new BookService();//dependency
service.add(book);
}
}
class Book{
private int bookId;
private String name;
private String author;
Book(int bookId,String name,String author){
this.bookId=bookId;
this.name=name;
this.author=author;
}
//getters & setters
}
class BookService{
private BookDAO bookDao = new BookDAO();//dependency
public void add(Book book){
bookDao.save(book);
}
}
class BookDAO{
private JdbcRepository repository = new JdbcRepository();//dependency
public void save(Book book){
repository.save(book);
}
}
How can we reduce coupling?
Program to interfaces(Still have coupling because of new operator).
Dependency Injection(Pass collaborators in as parameters rather than hard-coding them).
Centralize Configuration(Capture all the dependencies in one place. Use a "container" to create and configure your objects.)
public class Client {
public static void main(String[] args) {
BookService service = Container.getBookServiceInstance();
Book book = new Book(1,"Effective Java","Joshua Bloch");
General expectation of client from core java developer is he should strong in Data structure , multithreading and fundamental , client expect when complex question asked from candidate he should attempt and try to solve the problem, the idea of asking complex question is they want to see are developer attempting to solve the problem which he has never solved , if trying to solve what approach taking , how breaking a problem into small part ,how using design principle and pattern.
some time client asking an open-ended question, the purpose of asking the open-ended question is, the developer should answer based on his past experience if developer answer in totality with confidence the probability of clearing interview become very high
the idea of asking the ambiguous question is the developer should be asked a question to clarify the requirement if the requirement is not clear and then try to solve the problem
Problem Solving
The idea of asking problem-solving is to evaluate developer design skills, sometimes client not expecting concrete implementation, they want to understand what approach developer taking to solve the design problem, are they giving up or the attempting to solve the problem
Fundamental
In fundamental client expecting , developer should know purpose of all the keyword , static binding , dynamic binding , overloading rule , overriding rule in terms of access modifier, exception handling, impact of dynamic linking on performance , how to improve performance by using final keyword , whats default implementation of hash code and equal , cloning, immutability, advantage of immutability , importance of final in security , Exception handling rules
Data Structure
In Data structure the expectation is developer should know all basic data structure and how those basic data structures internally working , base on use case developer should answer question which data structure is the best fit for given use case , how hashing concept is working in hash set and map , how to improve map /set performance by optimizing hash code , whats are time complexity of different operation on data structure , how resizing is happening in data structure , how to use comparable comparator , how to implement different sorting algorithm . How to optimize data structure by changing the capacity and load factor could able to implement one data structure by using another, could able to answer how to implement the data structure
Concurrent API
developer should know how concurrent hash map internally managing a lock how segmentation is working ,how many thread can work on concurrent hash map , benefit of using concurrent hash map over hash table and synchronize map , what kind of business use case can be implemented by using concurrent hash map , how blocking queue is working what kind of problem can be solved by using blocking queue, when we should use linked blocking queue and when array blocking queue whats implementation of blocking queue, how to use blocking queue in inter-thread communication, whats fail-safe iterator
how to implement thread pool, whats advantage of the thread pool, how many types of thread pool do we have, how we can use executor service, how to use executor service to implement parallel /pipeline processing. , what kind of business problem can be solved by a cyclic barrier and count down the latch and how it's working, how to use semaphore, whats CAS concept (Compare and set), how atomic API is working internally
Multithreading
the expectation here is developer should know basic of multithreading, should know how to wait, notify, sleep, join is working, how locking is working , whats class label lock , whats object lock, how to implement inter-thread communication by using wait and notify , how volatile is working , how happen before concept is working in terms of volatile , how to implement thread pool in java 4 , how important is immutability in multithreading , whats code can create deadlock, what code can create starvation,
Serialization
Developer should know the purpose of serialization, purpose of serial version UID, if serial version UID is not defined how JVM generating it, how to customize serialization behavior, how to serialize transient variable how to improve performance by customizing serialization behavior
Memory management
Developer should know java memory model , should know heap , how garbage collection is working , how to optimize memory , should aware where class metadata storing in memory, should know reason of Perm gen Exception, reason of Out of memory exception, should aware how to do memory profiling, how to identify which code consuming memory
Design Pattern
Developers should know at least 2 to 3 design patterns thoroughly while explaining use case implementation should use some of the design patterns, must know the best way of implementing singleton pattern, factory pattern, strategy pattern, builder pattern, flyweight pattern, decorator and adapter pattern. Should know at-least 1 example of these patterns implementations from JDK.
Design Principle
Developer should know SOLID concept very well, whenever explaining solution design principle should reflect in his solution, how important is code for interface concept
Object-oriented Concept
Developer should know Encapsulation, Polymorphic, Composition, Inheritance, when should use inheritance when should we use composition.
Database
Developer should able to write some of the queries on join and aggregation, Should aware index, type of index and how indexing is working, should aware all key
Spring
Knows basics of Spring-like dependency injection (inversion of control), auto wiring (both XML and annotations), bean life cycle, profiling, transaction management and externalization of properties.
Rest
Basic understanding of REST principles (Uniform interface, Stateless interactions, Cacheable, Client-Server, Layered System, Code on Demand. HTTP protocol (HTTP methods, Headers, Error codes) and the concept of resources for REST.
Micro-Services
What is MicroServices? How it is different from Monolithic architecture? what are the advantages in Microservices w.r.t Monolithic architecture? Small application using Spring boot.
Lambda Expression a.k.a Anonymous Function.
A function having no
1. Name
2. Return type
3. Modifiers
Let's understand the above concept with the help of an example.
Take a method having name m return type int and modifier public
public int m(){};
Note here; is optional
Now apply the Lambda Expression to the above method.
public int m(){};
means remove
1. Name i.e m
2. Return type i.e int
3.Access Modifiers i.e public
After removing it becomes
() {}
To make it Lambda express we have a link with arrow symbol -> like below. ()->{}; Note here; is mandatory.
Important points to Remember
The method parameter type is optional, Compiler automatically knows the method parameter type which is called Type Inference. You know Functional Interface contains only one abstract method so the compiler can guess the type of parameter.
If there is only one parameter then parenthesis () is also optional.
If there is only one statement inside the method body then curly braces also optional. But if you are removing {} then also remove the return keyword otherwise you will get a compilation error.
If there is no parameter then parenthesis is mandatory.
If there are more than one parameters then also parenthesis is mandatory.
Convert below methods in lamda expression Example1
public int add(int a,int b) {
return a+b;
}
(int a,int b)->{return a+b};//valid
(a,b)->{return a+b};//valid
(a,b)->return a+b;//invalid
(a,b)->a+b;//valid
a,b->{return a+b;};//invalid
Now think how can you invoke the above lambda express.
The answer is using the Functional Interface.
Functional Interface.
Functional Interfaces are those which will satisfy the below rules.
1. Having only one abstract method.
2. No restriction with the default method
3. No restriction with the static method. For example
public interface InterF {
public void m();
default void m2() {
}
default int m3() {
return 0;
}
public static void m4() {
}
public static void m5() {
}
}
Q. How can we invoke Lambda expression? Ans: Using Functional Interface. InterF f=()->{System.out.println("hello");}; f.m();
Note: In Java 1.8v @FunctionalInterface annotation is introduced to specify that the interface is Functional interface and if you not abide functional interface rules then you will get compilation error.
Example
@FunctionalInterface
public interface InterF {
public void m1();
public void m2();
}//you will get compilation error. Functional Interface w.r.t Inheritance
If an interface extends Functional Interface and child interface doesn't contain any abstract method then the child interface is also a Functional Interface.
@FunctionalInterface
public interface InterA {
public void m1();
}
@FunctionalInterface
public interface InterB extends InterA {
public void m1();
}//No compilation error.
@FunctionalInterface
public interface InterB extends InterA {
public void m2();//compilation error
}
public interface InterB extends InterA {
public void m2();//No compilation error because this is not a functional interface. it is a normal interface which can contain any number of abstract methods
}
The wrapper classes are used to wrap primitives in an object. So, they can be added to a collection object.
To define utility functions that are required for the primitives.
All wrapper classes are immutable.
Wrapper classes Byte, Short, Integer and Long cache objects with values in the range of -128 to 127. The Character class caches objects with values 0 to 127.
Wrapper classes Float and Double don't cache objects for any range of values.
Example:
public class Test{
public static void main(String[] args){
Integer a =10;
Integer b=10;
System.out.println(a==b);//true
Integer c=128;
Integer d =128;
System.out.println(c==d);//false,reason value 128 is out of range of cache objects .So it will create new object.
}
}
Creating object of the wrapper classes You can create objects of all the wrapper classes in multiple ways Assignment : By assigning a primitive to a wrapper class variable(Auto-boxing)
Ex: Integer a =10; Constructor: By using wrapper class constructors.
Ex: Integer a = new Integer(10); Static methods: By calling static method of wrapper classes, like valueOf();
Ex:Integer wrapper = Integer.valueOf(10); Wrapper Classes Constructors
Wrapper Class
Constructors
Byte
Byte(byte a),Byte(String s)
Short
Short(short a),Short(String s)
Integer
Integer(int a),Integer(String s)
Long
Long(long a),Long(String s)
Float
Float(float a),Float(String s)
Double
Double(double a),Double(String s)
Character
Character(char a)
Boolean
Boolean(boolean a),Boolean(String s)
Note: Wrapper class Character has no String argument constructor. The class hierarchy of wrapper class
Conversion of Wrapper Classes to String and Primitive and Vice-Versa String to Wrapper Class:
Integer wrapper= Integer.valueOf("10");
String to Primitive:
int primitive = Integer.parseInt("10");
Wrapper to String:
String String1= String.valueOf(wrapper);
String String2 = wrapper.toString();
Wrapper to primitive:
int intValue = wrapper.intValue();
Primitive to Wrapper:
Integer wrapper = Integer.valueOf(10);
Primitive to String:
String string3 = Integer.toString(10);