Java is platform independent ,object-oriented programming language.
- Byte code - Java source code is complied into platform-independent byte code which can be executed by an JVM. Java byte code can be executed on any device with a compatible JVM from smartphones to computer.
- JVM - Java virtual machine has its own run time environment which executes byte code. JVM is platform dependent, because every operating environment has its own JVM.
- Platform Independent- Write once, run anywhere.
- Object-Oriented- Emphasizes on classes and objects, therefore promoting OOPS concepts.
- Secure - Java programs runs inside a virtual machine, therefore it's secure.
JVM-
- JVM Interprets Java byte code into machine specific instructions
- Memory Management - Handles memory management include garbage collection.
- JIT compilation - Converts byte code to machine code.
- Exception Handling - Manages exception handling.
JRE- The JRE (Java Runtime Environment) is the minimum environment required to execute a Java application.
JDK- JDK includes development kit, providing everything need to for java application development. javac: The Java compiler java: The Java application launcher
There are 2 data types in java. Primitive data type and non primitive data type in java.
Stack Memory -> When we write a program, then all variables, methods and object reference are stored in stack memory. Heap Memory -> When we create an object, the object is stored in heap memory and reference is stored in stack. The object is created at run time and heap memory is available for run time things. Heap memory is like a big storage.
Instance variables -> are variables declared outside the method but inside the class.These variables belong to object and we access them using object creation. Local Variables -> are variables present inside block, method or constructor and its access is limited within them.
7. What is the significance of using super to call a constructor from a super class with parameters.
Using super(parameters) ensures that super class constructors is called with necessary parameters, initializing inherited fields.
8. How does this assist in resolving conflicts between instance variables and method parameters in a class?
This keyword refers to current class instance variables and is used to differentiate local variables and instance variables when they have same name.
Abstract class defines common methods, providing a base that multiple other classes and extend and use.
Method overloading allows multiple methods with same name but different no and type pf parameters, therefor making it more flexible and reusable.
Interface defines a common set of methods that test classes should implement, ensuring a standardized approach. Interface must define a contract that multiple class should adhere.
- Primitive data type
- Memory allocation: Fixed
$32$ bits (or$4$ bytes) - Instantiation: Direct, no constructor required
- Default value:
$0$ - Performance: Generally faster due to direct value storage
- Wrapper class for the primitive
int
- Provides additional functionality via class methods
- Memory allocation: Variable, typically more than
int
- Instantiation: Through constructor, auto-boxing, or
valueOf()
- Default value:
null
(if not assigned) - Performance: Slightly slower due to object overhead
Wrapper classes in Java allow you to work with primitive data types as objects. They are particularly useful when working with generic collections or when using features that require objects, such as Java Bean properties.
Wrapper classes not only provide a way to convert primitives to and from objects but also offer various utility methods specific to each primitive type.
Integer.parseInt --> While working upon strings, there are times when we need to convert a number represented as string to integer type. We can use parseInt method from Integer class. It takes string as parameter and parses it into primitive data type int.
public static int parseInt(String s) throws NumberFormatException
int num = Integer.parseInt(str);
Primitive | Wrapper Class | Conversion Methods | Primitive Example | Wrapper Example |
---|---|---|---|---|
boolean |
Boolean |
.valueOf() .parseBoolean() .booleanValue() |
true |
Boolean.TRUE |
byte |
Byte |
.valueOf() .parseByte() .byteValue() |
123 |
Byte.valueOf((byte)123) |
char |
Character |
.valueOf() .charValue() |
'a' |
Character.valueOf('a') |
short |
Short |
.valueOf() .parseShort() .shortValue() |
123 |
Short.valueOf((short)123) |
int |
Integer |
.valueOf() .parseInt() .intValue() |
123 |
Integer.valueOf(123) |
long |
Long |
.valueOf() .parseLong() .longValue() |
123L |
Long.valueOf(123L) |
float |
Float |
.valueOf() .parseFloat() .floatValue() |
123.45f |
Float.valueOf(123.45f) |
double |
Double |
.valueOf() .parseDouble() .doubleValue() |
123.45 |
Double.valueOf(123.45) |
Collections in Java require objects, not primitives. Wrapper classes allow you to use primitives in these collections.
List<Integer> numbers = new ArrayList<>();
numbers.add(5); // Autoboxing: int to Integer
int num = numbers.get(0); // Unboxing: Integer to int
Wrapper classes can represent the absence of a value using null
, which primitives cannot.
Integer age = null; // Valid
int primitiveAge = null; // Compilation error
Wrapper classes provide useful utility methods for their respective types.
String binaryString = Integer.toBinaryString(42);
int maxValue = Integer.MAX_VALUE;
boolean isDigit = Character.isDigit('7');
Java is not a pure object-oriented language. While it incorporates many object-oriented programming (OOP) principles, it retains some elements from procedural programming.
Java supports the four main pillars of OOP:
- Encapsulation: Achieved through access modifiers (
public
,private
,protected
). - Abstraction: Implemented via abstract classes and interfaces.
- Inheritance: Supported using the
extends
keyword for classes andimplements
for interfaces. - Polymorphism: Realized through method overloading and overriding.
-
Primitive Data Types: Java includes non-object primitives like
int
,boolean
,char
, etc. -
Static Members: The
static
keyword allows for class-level fields and methods, not tied to object instances. -
Procedural Constructs: Java supports procedural programming elements such as control flow statements (
if
,for
,while
, etc.).
- String are immutable in java means, once a String object is created it cannot be modified.
- String pool is only possible because of immutable behavior.Different String variables can refer to same object in pool.
- Since String is immutable, it is safe for multi threading. A single String instance can be shared across different threads.
-
Single Inheritance- When a class inherits properties and behavior of only one class.
-
Hierarchical Inheritance- When multiple class inherits the properties and behavior of one class, its called as Hierarchical Inheritance. ex-
-
In selenium project we have BasePage abstract class which extends multiple page classes.
-
Multiple Inheritance is not supported in Java, because if one class inherits same method from multiples parent class then compiler cannot decide method from which classes it needs to invoke.
Means same thing in different form.
-
Method Overloading- Same method name with different number of parameters and type of parameters.
-
In Selenium project we have 2 selectDropDown methods which has same but different signatures.
-
Method Overriding - Same method name with same signature, just the implementation changes.
Hiding the implementation and showing only functionality to user.
-
Using Abstract Class - In our selenium project we have BasePage abstract class which has common methods for all the child page classes. In this BasePage abstract class we can define abstract and non-abstract methods.
-
Interface includes only abstract methods. 100% abstraction.
- Binding the data and methods together. Defining private variables and using public getters and setters.
final is a keyword used in java.
- final for a class means it cannot be extended. Ex We have Properties class in utils package which is a final class.
- final for a variable means its value is constant and cannot be modified.
- final for method means it cannot be overridden.
Static means attached to the class. For example if we have a variable in a class that will have same value for all the objects, we can make it static so it be directly accessed and that way we save memory. Ex 3 cars having same color as red, we can make color as static. static variables or methods can be directly accessed and doesn't need object creation.
The Collection in Java is a framework that provides an architecture to store and manipulate the group of objects. Java Collections can achieve all the operations that we perform on a data such as searching, sorting, insertion, manipulation, and deletion.
Java Collection means a single unit of objects. Java Collection framework provides many interfaces (Set, List, Queue, Deque) and classes (ArrayList, Vector, LinkedList, PriorityQueue, HashSet, LinkedHashSet, TreeSet).
Collection Interface
Collection interface is at the root of the hierarchy. Collection interface provides all general purpose methods which all collections classes must support (or throw UnsupportedOperationException). It extends Iterable interface which adds support for iterating over collection elements using the “for-each loop” statement.
1. List
Lists represents an ordered collection of elements. Using lists, we can access elements by their integer index (position in the list), and search for elements in the list. index start with 0, just like an array.
Some useful classes which implement List interface are – ArrayList, CopyOnWriteArrayList, LinkedList, Stack and Vector.
2. Set
Sets represents a collection of sorted elements. Sets do not allow the duplicate elements. Set interface does not provides no guarantee to return the elements in any predictable order; though some Set implementations store elements in their natural ordering and guarantee this order.
Some useful classes which implement Set interface are – ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, LinkedHashSet and TreeSet.
3. Queue A queue data structure is intended to hold the elements (put by producer threads) prior to processing by consumer thread(s). Besides basic Collection operations, queues provide additional insertion, extraction, and inspection operations.
Some useful classes which implement Map interface are – ArrayBlockingQueue, ArrayDeque, ConcurrentLinkedDeque, ConcurrentLinkedQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedList, LinkedTransferQueue, PriorityBlockingQueue, PriorityQueue and SynchronousQueue.
- List is ordered, set is unordered.
- List allows duplicates, set doesn't allow duplicates.
- List allows null values, set allows a single null.
Map
The Map interface enable us to store data in key-value pairs (keys should be immutable). A map cannot contain duplicate keys; each key can map to at most one value.
The Map interface provides three collection views, which allow a map’s contents to be viewed as a set of keys, collection of values, or set of key-value mappings. Some map implementations, like the TreeMap class, make specific guarantees as to their order; others, like the HashMap class, do not.
Some useful classes which implement Map interface are – ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable, IdentityHashMap, LinkedHashMap, Properties, TreeMap and WeakHashMap.
Linked HashMap- LinkedHashMap is just like HashMap with an additional feature of maintaining an order of elements inserted into it
The Java Collections Framework provides the following benefits:
- Reduces programming effort
- Increases program speed and quality
- Allows interoperability among unrelated APIs
- Reduces effort to learn and to use new APIs
- Reduces effort to design new APIs
- Fosters software reuse
Methods of Collection Interface
No. | Method | Description |
---|---|---|
1 | public boolean add(Object element) | is used to insert an element in this collection. |
2 | public boolean addAll(Collection c) | is used to insert the specified collection elements in the invoking collection. |
3 | public boolean remove(Object element) | is used to delete an element from this collection. |
4 | public boolean removeAll(Collection c) | is used to delete all the elements of specified collection from the invoking collection. |
5 | public boolean retainAll(Collection c) | is used to delete all the elements of invoking collection except the specified collection. |
6 | public int size() | return the total number of elements in the collection. |
7 | public void clear() | removes the total no of element from the collection. |
8 | public boolean contains(Object element) | is used to search an element. |
9 | public boolean containsAll(Collection c) | is used to search the specified collection in this collection. |
10 | public Iterator iterator() | returns an iterator. |
11 | public Object[] toArray() | converts collection into array. |
12 | public boolean isEmpty() | checks if collection is empty. |
13 | public boolean equals(Object element) | matches two collection. |
14 | public int hashCode() | returns the hashcode number for collection. |
If you know the size and the data type of elements, you can go with Arrays. Otherwise, go with a collection as a collection can store unlimited number of elements either of the same type or different types. Moreover, if you want to reduce coding effort, you can go with Collections, as it offers to use various utility methods. From the performance point of view, Array is better than a collection as utility methods take more time to execute.
- Resizable: Array is fixed sized array but ArrayList is dynamic sized array.
- Primitives: Array can contain both primitives and objects but ArrayList can contain only object elements
public class ArrayHomogenous {
public static void main(String args[]){
int[] arr =new int[5];//declaration and instantiation
// boolean[] boolArr = { true, true, false, true };
// char[] charArr = { 'g', 'e', 'e', 'k', 's' };
arr[0]=10;//initialization
arr[1]=20;
for(int i=0;i<arr.length;i++)//length is the property of array
System.out.println(arr[i]);
}}
public class ArrayListHomogeneousAndHeterogeneous {
public static void main(String[] args) {
ArrayList myNumbers = new ArrayList();
myNumbers.add("10");
myNumbers.add(15);
myNumbers.add(20);
for (Object i : myNumbers) {
System.out.println(i);
}
}
}
Homogeneous: A homogeneous collection in Java contains elements of the same type. For example, an array or a list declared to hold integers (int[], ArrayList) is homogeneous because all its elements are of type int or Integer.
int[] numbers = {1, 2, 3, 4, 5};
List<Integer> ls = new ArrayList<>();
Object[] mixedArray = {1, "two", 3.0, true};
Heterogeneous: A heterogeneous collection in Java can contain elements of different types. This is typically achieved using the common ancestor type of all potential elements (like Object), allowing different types of objects to be stored in the same collection.
ArrayList myNumbers = new ArrayList();
myNumbers.add("10");
myNumbers.add(15);
myNumbers.add(20);
LinkedHashSet- Maintains insertion order. The only difference between HashSet and LinkedHashSet is that LinkedHashSet maintains the insertion order. The reason why LinkedHashSet maintains insertion order is because the underlying data structure is a doubly-linked list. HashSet does not maintain insertion order.
HashMap is non synchronized. It is not-thread safe and can't be shared between many threads without proper synchronization code. HashMap allows one null key and multiple null values.
Hashtable is synchronized. It is thread-safe and can be shared with many threads. Hashtable doesn't allow any null key or value.
Set:-
- Set does not allow duplicates. Set and all the classes which implements Set interface should have unique elements.
- Set allows single null value at most.
- Set does not maintain any order; still few of its classes sort the elements in an order such as LinkedHashSet maintains the elements in insertion order.
- Classes used in sets are Set: HashSet, Linked HashSet, TreeSet, SortedSet etc.
Map:-
- Map stored the elements as key & value pair. Map doesn’t allow duplicate keys while it allows duplicate values.
- Map can have single null key at most and any number of null values.
- Set Map also doesn’t stores the elements in an order, however few of its classes does the same.
- Classes in Maps HashMap, TreeMap, WeakHashMap, LinkedHashMap, IdentityHashMap etc.
HashSet:-
- HashSet class implements the Set interface
- HashSet does not allow duplicate elements that mean you can not store duplicate values in HashSet.
- HashSet permits to have a single null value.
- HashSet is not synchronized which means they are not suitable for thread-safe operations until unless synchronized explicitly.
HashMap:-
- HashMap class implements the Map interface
- HashMap is used for storing key & value pairs. In short, it maintains the mapping of key & value (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.) This is how you could represent HashMap elements if it has integer key and value of String type: e.g. {1->”Hello”, 2->”Hi”, 3->”Bye”, 4->”Run”}
- HashMap does not allow duplicate keys however it allows having duplicate values.
- HashMap permits single null key and any number of null values.
- HashMap is not synchronized which means they are not suitable for thread-safe operations until unless synchronized explicitly.
Tree map is used when we require key values pair in sorted ascending order.
“Collection” is an interface. If we want to represent a group of individual objects as a single entity, then we should go for Collection.
“Collections” is an utility class present in java.util package to define several utility methods for Collection objects (like sorting, searching, etc).
Call by value- If we call a method by passing the value in the method parameter, this is known as call by value. This does not change original value, just a copy of value is sent to the method.
Garbage collection is a mechanism where JVM deletes unreferenced objects from memory and it runs finalize method before running this process.
Parent to child is upcasting
Child to parent is downcasting
Parent p = new Child():
Upcasting involves assigning superclass reference variable to child class object.This helps to access parent clas members and overridden methods of child class. Upcasting supports polymorphism.
An Exception is an event that disrupts the normal flow of the program. Exception Handling is a mechanism to handle runtime errors such as ClassNotFoundException, IOException, SQLException, RemoteException, etc.
Benefits-
- Prevents program crashes.
- Provides info about error.
- Allows to recover from errors.
There are 2 main types of exception-
- Checked Exception - Compile time exception are known as checked exceptions. IO and SQL
- Unchecked Exception - Run time exception like arithmetic exception, null pointer exception and all.
public class MyException extends Exception{
private String message;
public MyException(String message){
super(message);
this.message = message;
}
public String getMessage(){
return message;
}
}
Multithreading is a programming concept that allows multiple task to be executed at the same time. In Java multithreading is implemented using Thread class.
Synchronization in Java is a mechanism that allows multiple threads to access shared resource safely.This prevents the race condition where two or more threads are trying to access the same resource at the same time. There are 2 ways to synchronize in java-
- Using Synchronized methods
A synchronized method is a method that can only be executed by one thread at a time. To declare a method as synchronized you need to use synchronized keyword.
When a particular resource is shared between multiple threads, situation may arise when multiple threads require same shared resource. Synchronization helps in resolving this issue by allowing only single thread to access the resource at a time.
Without Synchronization
public class Counting{
private int increase_counter;
public int increase(){
increase_counter = increase_counter + 1;
return increase_counter;
}
}
If thread1 view count as 10, it will increase to 11. Simultaneously thread2 views count as 10, it will increase to 11.This inconsistency is caused because of this.
With Synchronization
public class Counting{
private int increase_counter;
public Synchronized int increase(){
increase_counter = increase_counter + 1;
return increase_counter;
}
}
a static block is a set of instructions that is run only once when a class is loaded into memory. In out automation framework we have PropertyUtils class which has a static block to read the config file and store the values in a static map object to be used in another parts of the programs. like username, password and other configuration details. This static block is called as soon as the class in loaded, even before the main method.
public class PropertyUtils {
private static Properties property= new Properties();
private static final Map<String, String> configMap= new HashMap<>();
static {
try {
FileInputStream file = new FileInputStream(FrameworkConstants.getConfigFilePath());
property.load(file);
for (Map.Entry<Object, Object> entry : property.entrySet()) {
configMap.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()).trim()); //remove the trailing and leading spaces
}
}
catch(Exception e){
}
}
}
Private constructor job is restrict object creation outside the class. We can create object inside the class.
In the following example, we want to insert three (Key, Value) pair in the HashMap.
HashMap<String, Integer> map = new HashMap<>();
map.put("Adi", 19);
map.put("Mona", 29);
map.put("Divisha", 39);
When we call the put() method, then it calculates the hash code of the Key "Adi." Suppose the hash code of "Aman" is 2657860. To store the Key in memory, we have to calculate the index.
Index = hashcode(Key) & (n-1)
Index = 2657860 & (16-1) = 4
The value 4 is the computed index value where the Key and value will store in HashMap.
get() method in HashMap
-
get() method is used to get the value by its Key. It will not fetch the value if you don't know the Key
hashCode()
: This is the method of the object class. It returns the memory reference of the object in integer form.
Hashing
: When you insert a key-value pair into the HashMap, Java computes the hash code of the key using the hashCode() method. The hash code is then used to determine the index (bucket) where the key-value pair will be stored in the array.
Internally HashMap maintains a bucket array, with initial capacity as 16. Each index in the array can hold multiple node objects using LinkedList.As shown above, it is possible that multiple keys may produce the hash that maps them into a single bucket. This is why, the Map entries are stored as LinkedList.
- Singleton pattern restricts the instantiation of a class and ensures that only one instance of the class exists in the Java Virtual Machine.To achieve this we create a private constructor in the class.
- The singleton class must provide a global access point to get the instance of the class. We create a public static getInstance method to provide access to object.
In our automation framework we have created a thread-safe singleton class. We have created an instance of Thread Local class to make driver variable thread safe.
This design pattern can be used for driver objects as only one object is required per thread.
String
is immutable, creating new objects for modifications, consuming memory and slowing execution.
StringBuilder
is mutable, making it efficient for frequent concatenation, string modification, and large string construction. It reduces execution time by avoiding unnecessary object creation during concatenation and dynamic memory allocation for large strings.
Immutable
: In Java, a String is an immutable object. This means that once a String object is created, its content cannot be changed. Any operation that seems to modify a String actually creates a new String object with the modified content, leaving the original String unchanged.
String str1 = "Hello";
String str2 = str1.concat(", World"); // Creates a new String
System.out.println(str1); // Output: Hello
System.out.println(str2); // Output: Hello, World
Memory Allocation
: When you perform operations on a String, such as concatenation or substring extraction, it often leads to the creation of new String objects. This behavior can consume additional memory.
Efficiency for Concatenation
: If you concatenate multiple strings in a loop using + or concat(), it can lead to poor performance due to the creation of multiple intermediate String objects.
Mutable
: StringBuilder in Java is designed to be mutable. It allows you to modify the contents of the string without creating new String objects. The modifications are done in the same memory location, making it more memory-efficient.
StringBuilder stringBuilder = new StringBuilder("Hello");
stringBuilder.append(", World"); // Modifies the StringBuilder in place
String result = stringBuilder.toString(); // Converts to String
System.out.println(result); // Output: Hello, World
Memory Allocation
: StringBuilder dynamically allocates memory as needed to accommodate the modified string content. It doesn't create new objects for each modification, reducing memory overhead.
Efficiency for Concatenation
: If you need to concatenate or modify strings frequently, StringBuilder is much more efficient than using + or concat() because it avoids the creation of unnecessary String objects.
In conclusion, when it comes to concatenation or modification operations, StringBuilder demonstrates significantly faster performance compared to the String class. Modifying a String results in the creation of a new object in heap memory, which can lead to performance inefficiencies. In contrast, the StringBuilder class is well-suited for modifying string content without generating additional objects in memory. This makes it the ideal choice for efficient string manipulation