CAT-1 Question Bank
CAT-1 Question Bank
Answer:
The meaning of Java platform-independent is that the Java compiled code(byte code)
can run on all operating systems. A program is written in a language that is a human-
readable language. It may contain words, phrases, etc which the machine does not
understand. For the source code to be understood by the machine, it needs to be in a
language understood by machines, typically a machine-level language. So, here
comes the role of a compiler. The compiler converts the high-level language (human
language) into a format understood by the machines.
Therefore, a compiler is a program that translates the source code for another program
from a programming language into executable code. This executable code may be a
sequence of machine instructions that can be executed by the CPU directly, or it may
be an intermediate representation that is interpreted by a virtual machine. This
intermediate representation in Java is the Java Byte Code.
In the case of C or C++ (languages that are not platform independent), the compiler
generates a .exe file which is OS dependent. When we try to run this .exe file on
another OS it does not run, since it is OS-dependent and hence is not compatible with
the other OS.
In Java, the main point here is that the JVM depends on the operating system – so if
you are running Mac OS X you will have a different JVM than if you are running
Windows or some other operating system. This fact can be verified by trying to
download the JVM for your particular machine – when trying to download it, you will
be given a list of JVMs corresponding to different operating systems, and you will
obviously pick whichever JVM is targeted for the operating system that you are
running. So we can conclude that JVM is platform-dependent and it is the reason why
Java is able to become “Platform Independent”.
Hence, Multiple inheritance is not supported by Java using classes, handling the
complexity that causes due to multiple inheritances is very complex. It creates
problems during various operations like casting, constructor chaining, etc, and the
above all reason is that there are very few scenarios on which we actually need
multiple inheritances, so better to omit it for keeping things simple and
straightforward.
But the same can be handled by using interfaces. A class can implement two or
more interfaces. In case both the implemented interfaces contain default methods
with the same method signature, the implementing class should explicitly specify
which default method is to be used in some method excluding the main() of
implementing class using super keyword, or it should override the default method in
the implementing class, or it should specify which default method is to be used in
the default overridden method of the implementing class.
class RunTimePolymorphismParentClassExample {
public void display() {
System.out.println("Overridden Method");
}
}
Answer:
The Java compiler breaks the line of code into text (words) is called Java tokens.
These are the smallest element of the Java program. The Java compiler identified
these words as tokens. These tokens are separated by the delimiters. It is useful for
compilers to detect errors. Remember that the delimiters are not part of the Java
tokens.
Primitive data types: The primitive data types include boolean, char, byte, short, int,
long, float and double.
Non-primitive data types: The non-primitive data types include Classes, Interfaces,
and Arrays.
Answer: Garbage collection in Java is the process by which Java programs perform
automatic memory management. Java programs compile to bytecode that can be run
on a Java Virtual Machine, or JVM for short. When Java programs run on the JVM,
objects are created on the heap, which is a portion of memory dedicated to the
program. Eventually, some objects will no longer be needed. The garbage collector
finds these unused objects and deletes them to free up memory.
But in Java, the programmer need not care for all those objects which are no longer in
use. Garbage collector destroys these objects. The main objective of Garbage
Collector is to free heap memory by destroying unreachable objects. The garbage
collector is the best example of the Daemon thread as it is always running in the
background.
Two types of garbage collection activity usually happen in Java. These are:
1. Minor or incremental Garbage Collection: It is said to have occurred when
unreachable objects in the young generation heap memory are removed.
2. Major or Full Garbage Collection: It is said to have occurred when the objects
that survived the minor garbage collection are copied into the old generation or
permanent generation heap memory are removed. When compared to the young
generation, garbage collection happens less frequently in the old generation.
Example:
class garbage
{
public void finalize()
{
System.out.println("object is garbage collected");
}
class RR {
// instance variable
int a = 10;
// static variable
void GFG()
// instance variable(i.e, a)
this.a = 100;
System.out.println(a);
// static variable(i.e, b)
this.b = 600;
System.out.println(b);
}
public static void main(String[] args)
// this.a = 700;
new RR().GFG();
Output
100
600
There are certain key points that are needed to be remembered before adhering
forward where we will be discussing and implementing static and dynamic bindings
in Java later concluding out the differences.
private, final and static members (methods and variables) use static binding
while for virtual methods (In Java methods are virtual by default) binding is
done during run time based upon the run time object.
The static binding uses Type information for binding while Dynamic binding
uses Objects to resolve to bind.
Overloaded methods are resolved (deciding which method to be called when
there are multiple methods with the same name) using static binding while
overridden methods use dynamic binding, i.e, at run time.
Static Binding
The binding which can be resolved at compile time by the compiler is known as
static or early binding. The binding of all the static, private, and final methods is
done at compile-time.
Example:
Java
// Main class
class NewClass {
// Class 1
// Print statement
System.out.println(
}
}
// Class 2
// print statement
System.out.println(
{
// Creating objects of static inner classes
A.print();
B.print();
Output
print() in superclass is called
print() in superclass is called
Output Explanation: As you can see, in both cases the print method of the
superclass is called. Let us discuss how this happens
We have created one object of subclass and one object of the superclass with the
reference of the superclass.
Since the print method of the superclass is static, the compiler knows that it will
not be overridden in subclasses and hence compiler knows during compile time
which print method to call and hence no ambiguity.
As an exercise, the reader can change the reference of object B to subclass and then
check the output.
Dynamic Binding
// Main class
// Class 1
void print()
// Print statement
System.out.println(
}
// Static nested inner class
// Class 2
// Print statement
System.out.println(
A.print();
B.print();
Output
print in superclass is called
print in subclass is called
Output Explanation: Here the output differs. But why? Let’s break down the code
and understand it thoroughly.
Methods are not static in this code.
During compilation, the compiler has no idea as to which print has to be called
since the compiler goes only by referencing variable not by the type of object,
and therefore the binding would be delayed to runtime and therefore the
corresponding version of the print will be called based on type on an object
There are certain advantages associated with inner classes are as follows:
Making code clean and readable.
Private methods of the outer class can be accessed, so bringing a new
dimension and making it closer to the real world.
Optimizing the code module.
Inner classes are classified into four types: static, non-static, local and anonymous.
These are the simplest type of inner classes. Static inner classes are those that are
declared inside a class and marked static. It should be noted that these classes can
only be accessed using an instance of the outer class. You can take advantage of static
nested classes for grouping related classes together.
Local inner classes are defined within a method. They have access to all the members
(variables and methods) of the enclosing class but they cannot be instantiated from
outside the method in which they are defined. An inner class defined locally may only
be instantiated inside its method where it has been defined.
A method local inner class is accessible only within the method in which it was
defined, and cannot be referenced by any other code outside the method in which it is
defined. A method local inner class can access local variables from the enclosing
scope (including final variables).
Anonymous Inner Classes
Inner classes that don’t have names are also known as anonymous inner classes. Both
the declaration and instantiation of an anonymous inner class occur simultaneously.
Anonymous inner classes cannot have explicit constructors, just like all local inner
classes. Anonymous inner classes are useful when you have to use a local inner class
only once.
Secured
Java is best known for its security. With Java, we can develop virus-free systems.
Java is secured because:
No explicit pointer
Robust
The English mining of Robust is strong. Java is robust because:
In C programming, int data type occupies 2 bytes of memory for 32-bit architecture
and 4 bytes of memory for 64-bit architecture. However, it occupies 4 bytes of
memory for both 32 and 64-bit architectures in Java.
Portable
Java is portable because it facilitates you to carry the Java bytecode to any platform. It
doesn't require any implementation.
High-performance
Java is faster than other traditional interpreted programming languages because Java
bytecode is "close" to native code. It is still a little bit slower than a compiled
language (e.g., C++). Java is an interpreted language that is why it is slower than
compiled languages, e.g., C, C++, etc.
Distributed
Java is distributed because it facilitates users to create distributed applications in Java.
RMI and EJB are used for creating distributed applications. This feature of Java
makes us able to access files by calling the methods from any machine on the internet.
Multi-threaded
A thread is like a separate program, executing concurrently. We can write Java
programs that deal with many tasks at once by defining multiple threads. The main
advantage of multi-threading is that it doesn't occupy memory for each thread. It
shares a common memory area. Threads are important for multi-media, Web
applications, etc.
Dynamic
Java is a dynamic language. It supports the dynamic loading of classes. It means
classes are loaded on demand. It also supports functions from its native languages,
i.e., C and C++.
Java is the most popular object-oriented programming language. It provides a variety of salient
features that are preferred by the developers. It is the reason that a billion of devices runs on Java.
In this section, we are going to discuss why Java is secure.
Java provides some other features that make Java more secure.
[1] JVM
[2] Security API's
[3] Security Manager
[4] Auto Memory Management
[5] No Concept of Pointers
[6] Compile-time Checking
[7] Cryptographic Security
[8] Java Sandbox
[9] Exception Handling
[10] ClassLoader
JVM
JVM plays a vital role to provide security. It verifies the byte-code. The JVM
provides guarantees that there is no unsafe operation going to execute. It also helps to
diminish the possibilities of the programmers who suffer from memory safety flaws.
Security API's
Java class libraries provide several API that leads to security. These APIs contain
cryptographic algorithms and authentication protocols that lead to secure
communication.
Byte Code
Every time when a user compiles the Java program, the Java compiler creates a class
file with Bytecode, which are tested by the JVM at the time of program execution for
viruses and other malicious files.
Security Manager
The security manager is responsible for checking the permissions and properties of
the classes. It monitors the system resources accessed by the authorized classes. It
also controls socket connections.
No Concept of Pointers
Java does not provide support for pointers concept. It is the main security features of
Java. The use of pointers may lead to unauthorized read or write operations.
Therefore, the user cannot point to any memory locations.
Memory management
Java automatically manages memory which is known as garbage collection. The JVM
manages memory itself. The programmers are free from memory management.
Hence, there is no chance to fault in memory management.
Compile-time checking
Compile-time checking also makes the Java secure. Consider a scenario in which an
unauthorized method is trying to access the private variable, in this case, the JVM
gives the compile-time error. It prevents the system from the crash.
Cryptographic Security
Java Sandbox
Exception Handling
The exception handling feature adds more security in Java. The feature reports the
error to the programmer during the runtime. The code will not run until the
programmer will not rectify it.
Java ClassLoader
There are a number of class loaders present in JVM. It provides and maintains
namespaces for specific classes. The advantage of the ClassLoader is that the
untrusted classes would not behave like a trusted one.
The fully qualified name of the loaded class and its immediate parent class.
Whether the “.class” file is related to Class or Interface or Enum.
Modifier, Variables and Method information etc.
After loading the “.class” file, JVM creates an object of type Class to represent this file in
the heap memory. Please note that this object is of type Class predefined
in java.lang package. These Class object can be used by the programmer for getting class
level information like the name of the class, parent name, methods and variable information
etc. To get this object reference we can use getClass() method of Object class.
Linking: Performs verification, preparation, and (optionally) resolution.
Verification: It ensures the correctness of the .class file i.e. it checks whether this file is
properly formatted and generated by a valid compiler or not. If verification fails, we get
run-time exception java.lang.VerifyError. This activity is done by the component
ByteCodeVerifier. Once this activity is completed then the class file is ready for
compilation.
Preparation: JVM allocates memory for class static variables and initializing the
memory to default values.
Resolution: It is the process of replacing symbolic references from the type with direct
references. It is done by searching into the method area to locate the referenced entity.
Initialization: In this phase, all static variables are assigned with their values defined in the
code and static block(if any). This is executed from top to bottom in a class and from parent
to child in the class hierarchy.
In general, there are three class loaders :
Bootstrap class loader: Every JVM implementation must have a bootstrap class loader,
capable of loading trusted classes. It loads core java API classes present in the
“JAVA_HOME/jre/lib” directory. This path is popularly known as the bootstrap path. It
is implemented in native languages like C, C++.
Extension class loader: It is a child of the bootstrap class loader. It loads the classes
present in the extensions directories “JAVA_HOME/jre/lib/ext”(Extension path) or any
other directory specified by the java.ext.dirs system property. It is implemented in java
by the sun.misc.Launcher$ExtClassLoader class.
System/Application class loader: It is a child of the extension class loader. It is
responsible to load classes from the application classpath. It internally uses Environment
Variable which mapped to java.class.path. It is also implemented in Java by
the sun.misc.Launcher$AppClassLoader class.