Chapter 1 - Introduction Flashcards
features of Java
Platform Independence - Java code is compiled into an intermediate form called bytecode, which can be executed on any platform with a Java Virtual Machine (JVM). This enables developers to write code once and run it on different platforms without modification.
Object-Oriented Programming (OOP)-
Java is based on the principles of OOP, which promotes the use of objects and classes for modeling and organizing code. This helps in creating modular, maintainable, and reusable code.
Java enforces strong type checking, which means that variable types are explicitly declared and checked at compile time. This helps catch type-related errors early in the development process.
Automatic Memory Management (Garbage Collection):
Java manages memory automatically through a garbage collector, which deallocates memory for objects that are no longer in use. This helps prevent memory leaks and simplifies memory management for developers.
Multi-threading and Concurrency:
Java provides built-in support for creating and managing threads, allowing developers to write concurrent and multithreaded programs. This is important for developing responsive and scalable applications.
Exception Handling:
Java has a robust exception-handling mechanism that allows developers to handle runtime errors gracefully, preventing abrupt program termination. This promotes better program stability.
Standard Library (Java API):
Java comes with a vast standard library (Java API) that includes pre-built classes and packages for various common tasks, such as I/O, networking, data structures, and more. This reduces the need for developers to reinvent the wheel.
Security:
Java has a strong emphasis on security, with features like bytecode verification, runtime security checks, and a security manager. This makes it a preferred choice for building secure applications, especially in web and enterprise environments.
Portability:
Java’s platform independence makes it highly portable. Applications written in Java can run on different operating systems without modification, as long as a compatible JVM is available for that platform.
Performance Optimization:
While Java is often associated with being slower than some low-level languages like C or C++, it offers features like Just-In-Time (JIT) compilation and performance tuning options to optimize the execution speed of Java applications.
Dynamic Loading and Reflection:
Java supports dynamic class loading and reflection, allowing applications to load classes and examine their properties at runtime. This enables advanced features like dynamic configuration and extensibility.
Java code lifecycle
Writing the Code:
The first stage involves writing the Java source code. You use a text editor or an Integrated Development Environment (IDE) like Eclipse, IntelliJ IDEA, or NetBeans to write your Java code. This code is typically saved with a .java extension.
Compilation:
After writing the Java code, you need to compile it. The Java source code is compiled into bytecode using the Java Compiler (javac). This bytecode is platform-independent and can be executed on any system with a Java Virtual Machine (JVM).
Bytecode Generation:
During compilation, the Java Compiler generates bytecode files with a .class extension for each class in your program. These bytecode files contain the low-level instructions that the JVM can understand.
Class Loading:
When you run a Java program, the JVM loads the necessary classes into memory. This process is called class loading. The JVM dynamically loads classes as they are needed during the program’s execution.
Initialization:
Once the classes are loaded, the JVM initializes the class variables and runs the static blocks of code, ensuring that classes and their dependencies are properly set up.
Main Method Execution:
Every Java application must have a main method with the following signature:
java
Copy code
public static void main(String[] args)
The JVM starts the program’s execution by invoking the main method, passing it an array of String arguments (args).
Runtime Execution:
During runtime, the program executes the statements within the main method and other methods called from main. It interacts with the JVM, the operating system, and external resources (e.g., files, databases, network services) as needed to perform its tasks.
Garbage Collection:
While the program is running, the JVM’s garbage collector periodically identifies and removes objects that are no longer in use, freeing up memory and preventing memory leaks.
Exception Handling:
During execution, the program may encounter exceptions or errors. Java provides mechanisms for handling these exceptions using try-catch blocks to prevent program crashes.
Termination:
The program’s execution eventually completes, either because it reaches the end of the main method or encounters a return statement. At this point, the program terminates, and any allocated resources are released.
Cleanup:
It’s good practice to include cleanup code, such as closing files or network connections, in a finally block or appropriate destructors to ensure that resources are properly released, even if an exception occurs.
Finalization:
In some cases, objects may need to perform finalization actions before they are reclaimed by the garbage collector. This is achieved by implementing the finalize() method in a class.
Shutdown Hooks:
You can register shutdown hooks using the Runtime.addShutdownHook() method to perform specific actions when the JVM is about to shut down, allowing you to release resources or perform cleanup tasks.
Variable in Java
variable is a named storage location that holds a value of a particular type. Variables are used to store and manipulate data during the execution of a program. Each variable has a data type, a name, and a value.
Variable features
Storage Location: A variable represents a storage location in computer memory where data can be stored and retrieved. This storage location has a unique name that allows you to reference it in your code.
Data Types: Variables have data types that define the kind of data they can hold. Common data types include integers (e.g., int), floating-point numbers (e.g., double), characters (e.g., char), and more complex types like strings (e.g., String).
Value Assignment: Variables can be assigned values, which can be literals (e.g., 5, ‘A’, “Hello”), results of calculations, or input from a user or external source.
Changing Values: The value of a variable can change during the execution of a program. This ability to change values is essential for performing calculations and maintaining state.
Primitive data types
primitive data types are the simplest data types used to represent basic values like numbers, characters, and boolean values. They are called “primitive” because they directly represent values at the lowest level, without being composed of other objects or data types. Java has eight primitive data types. byte,
short,
int
long
float
double
char
boolean
Byte type
it is used to represent 8-bit signed integers. Size and Range:
The byte data type is a 1-byte (8-bit) integer type.
It can represent integer values in the range of -128 to 127.
Default Value:
The default value of a byte variable is 0.
Memory Usage:
byte variables are used when you need to store small integers to conserve memory. They are especially useful when working with large arrays of data where memory efficiency is crucial.
byte is commonly used in situations where memory optimization is essential, such as when reading data from files or network streams, or when dealing with large collections of small integers.
ex
byte steps = 100;
Short data type
Size and Range:
The short data type is a 2-byte (16-bit) integer type.
It can represent integer values in the range of -32,768 to 32,767.
Default Value:
The default value of a short variable is 0.
Memory Usage:
short variables are used when you need to store small to moderately-sized integers. They offer a larger range than byte and are suitable for conserving memory while accommodating a broader set of integer values.
Use Cases:
short is used in scenarios where memory optimization is still important but a larger range of integer values is required compared to byte. It is suitable for various numeric applications, including scientific computing and embedded systems.
int
Size and Range:
The int data type is a 4-byte (32-bit) signed integer type.
It can represent integer values in the range of approximately -2 billion to 2 billion.
Default Value:
The default value of an int variable is 0.
Memory Usage:
int variables are used for storing whole numbers in a wide range. They are the most commonly used integer type in Java due to their balance of range and memory efficiency.
int is widely used for general-purpose integer arithmetic in Java. It is suitable for most scenarios where you need to represent and manipulate whole numbers.
Difference between primitive types and Wrapper classes
Data Representation:
Primitive Types: Primitive data types represent simple values directly and are not objects. They are stored directly in memory, which makes them more memory-efficient and faster to access.
Wrapper Classes: Wrapper classes are objects that encapsulate primitive data types. They provide a way to treat primitive types as objects and offer additional functionality, but they are less memory-efficient due to the overhead of object creation.
Nullability:
Primitive Types: Primitive types cannot have a null value. They always hold a valid value, even if it’s the default value (e.g., 0 for int, false for boolean).
Wrapper Classes: Wrapper classes can be assigned a null value because they are objects. This is useful when you need to represent the absence of a value.
Equality Comparison:
Primitive Types: You compare primitive types using the equality operators (== or !=) to check if their values are the same.
Wrapper Classes: Comparing wrapper class objects using == compares their references, not their values. To compare the values, you should use methods like equals().
Type Conversion:
Primitive Types: Type conversion between primitive types is done implicitly (e.g., widening conversions) or explicitly (e.g., narrowing conversions with casting).
Wrapper Classes: Type conversion between wrapper classes and primitive types requires explicit conversion using methods provided by the wrapper classes, like valueOf() and xxxValue() (e.g., intValue(), doubleValue()).
Methods and Utility:
Primitive Types: Primitive types do not have methods or utility functions. They are limited to basic mathematical and logical operations.
Wrapper Classes: Wrapper classes provide methods for converting, parsing, and manipulating the encapsulated values. For example, Integer has methods like parseInt() and toString().
Collections and Generics:
Primitive Types: You cannot use primitive types in collections (e.g., List<int>) or with Java generics.
Wrapper Classes: You can use wrapper classes with collections and generics, making them essential for working with data structures and algorithms that require objects.</int>
Auto(un)boxing:
Primitive Types: Do not support auto(un)boxing.
Wrapper Classes: Support auto(un)boxing, which allows automatic conversion between primitive types and their corresponding wrapper classes. For example, you can assign an int to an Integer without explicit conversion.
Long tyoe
represent integer values with a larger range than the int data type. Size and Range:
The long data type is a 64-bit signed integer type.
It can represent integer values in the range of approximately -9.2 quintillion (-9,223,372,036,854,775,808) to 9.2 quintillion (9,223,372,036,854,775,807).
Default Value:
The default value of a long variable is 0.
Memory Usage:
long variables use more memory than int variables due to their larger size. They are typically used when you need to represent very large integer values or when the range of values exceeds what an int can handle.
Explicit Casting:
When performing arithmetic operations involving long variables, the result is promoted to a long by default. You may need to explicitly cast the result to a narrower data type if you want to store it in a variable of that type.
Suffix:
To explicitly specify a long literal, you can use the suffix L or l. For example, long population = 7_900_000_000L;
Use Cases:
long is used when you need to represent very large integers, such as timestamps, unique identifiers, or quantities that exceed the range of int. It is also commonly used for operations involving large numerical calculations and when working with large datasets.
Wrapper Class:
The long data type has a corresponding wrapper class called Long, which is part of Java’s standard library. This wrapper class allows you to work with long values in an object-oriented manner and provides utility methods for working with long data.
long totalPopulation = 7_900_000_000L;
Float data type
Size and Precision:
The float data type is a 32-bit (4-byte) floating-point type.
It provides single-precision, which means it can represent decimal numbers with approximately 6-7 significant decimal digits.
Default Value:
The default value of a float variable is 0.0f.
Memory Usage:
float variables are used to store numbers with fractional parts (floating-point numbers) while conserving memory compared to the double data type. They are suitable for scenarios where precision is not a critical concern, and memory usage is a consideration.
Suffix:
To explicitly specify a float literal, you should use the suffix f or F. For example, float pi = 3.14159f;
Scientific Notation:
You can represent float values using scientific notation, which is often used for very large or very small numbers. For example, float scientificNumber = 1.23e-4f; represents 0.000123.
Approximate Representation:
Due to its limited precision, float values may not always represent decimal numbers exactly. This can lead to rounding errors, especially in complex mathematical operations.
Use Cases:
float is used when memory efficiency is a concern, and the application can tolerate some loss of precision. Common use cases include graphics programming, scientific simulations, and situations where memory is limited.
Wrapper Class:
The float data type has a corresponding wrapper class called Float, which is part of Java’s standard library. This wrapper class allows you to work with float values in an object-oriented manner and provides utility methods for working with float data.
float temperature = 25.5f;
Double
Size and Precision:
The double data type is a 64-bit (8-byte) floating-point type.
It provides double-precision, which means it can represent decimal numbers with approximately 15-16 significant decimal digits.
Default Value:
The default value of a double variable is 0.0.
Memory Usage:
double variables are used to store numbers with fractional parts (floating-point numbers) with higher precision compared to the float data type. They consume more memory but offer greater accuracy.
Suffix:
To explicitly specify a double literal, you don’t need a suffix. For example, double pi = 3.141592653589793;
Scientific Notation:
You can represent double values using scientific notation, which is often used for very large or very small numbers. For example, double scientificNumber = 1.23e-10; represents 0.000000000123.
Accuracy and Precision:
double is suitable for scenarios where high precision is required, such as scientific calculations, financial applications, and situations where exact representation of decimal numbers is essential.
Approximate Representation:
Like float, double values may not always represent decimal numbers exactly due to limited precision. Rounding errors can occur in complex mathematical operations.
Use Cases:
double is the default choice for representing floating-point numbers in Java when high precision is needed. It is widely used in scientific and engineering applications, financial calculations, and any situation where accurate representation of real numbers is critical.
Wrapper Class:
The double data type has a corresponding wrapper class called Double, which is part of Java’s standard library. This wrapper class allows you to work with double values in an object-oriented manner and provides utility methods for working with double data.
Char
primitive data types used to represent single characters from the Unicode character set.
Size:
The char data type is a 16-bit (2-byte) unsigned integer type.
Character Encoding:
It represents characters using the Unicode character encoding standard. Unicode is a universal character set that includes characters from most of the world’s scripts, allowing Java to support a wide range of characters and symbols.
Default Value:
The default value of a char variable is the null character, represented as ‘\u0000’.
Single Characters:
char is specifically used for representing single characters, such as letters, digits, symbols, and special characters.
Character Literals:
You can represent char literals by enclosing a single character in single quotes. For example, char letterA = ‘A’;.
Escape Sequences:
Special characters and escape sequences can be represented using backslashes. For example, char newline = ‘\n’; represents a newline character.
Unicode Escapes:
Unicode characters can be represented using Unicode escape sequences. For example, char euroSymbol = ‘\u20AC’; represents the Euro currency symbol.
Use Cases:
The char data type is used when you need to work with individual characters, such as reading and manipulating text, performing character-level operations, and representing symbols and special characters.
Wrapper Class:
Unlike most other primitive data types, there is no direct wrapper class for char. However, you can use methods from the Character class, which provides utility methods for working with char values.
Boolean
boolean data type is one of the primitive data types used to represent a binary state with two possible values: true or false. Size and Values:
The boolean data type has a fixed size of 1 bit, but its values are typically represented using a full byte (8 bits) in memory.
It can hold only two values: true and false. These values represent binary logic: true typically means “yes” or “on,” and false means “no” or “off.”
Default Value:
The default value of a boolean variable is false.
Logical Operations:
boolean variables are primarily used for logical and conditional operations. They are commonly used in if statements, loops, and control flow to make decisions based on conditions.
Comparison and Conditions:
boolean values are the result of comparison operations (e.g., a < b, x == y) and conditional expressions (e.g., if (condition)).
Use Cases:
The boolean data type is used to represent the truth value of a condition or the result of a logical operation. It’s essential for writing programs that involve decision-making and branching.
Wrapper Class:
The boolean data type has a corresponding wrapper class called Boolean, which is part of Java’s standard library. The Boolean class provides utility methods for working with boolean values in an object-oriented manner.
Widening (implicit) conversion
Widening conversion occurs when a value of a smaller data type is automatically promoted to a larger data type. Java handles this conversion automatically without the need for explicit casting. The widening conversion is considered safe because there is no loss of information.
Narrowing (explicit) conversion
process in Java where you manually convert a value from a wider data type to a narrower data type. Unlike widening conversions, which are performed automatically by the Java compiler when moving from a narrower data type to a wider one, narrowing conversions require explicit action from the programmer.
Arithmetic operators
Addition (+): int sum = num1 + num2
Subtraction (-):
The subtraction operator is used to subtract one numeric value from another.
Example: int difference = num1 - num2;
Multiplication (*):
The multiplication operator is used to multiply two numeric values.
Example: int product = num1 * num2;
Division (/):
The division operator is used to divide one numeric value by another.
Example: double quotient = (double) num1 / num2; (Note: Casting one operand to double ensures a floating-point result.)
Modulus (%):
The modulus operator returns the remainder of the division of one numeric value by another.
Example: int remainder = num1 % num2;
Increment (++):
The increment operator is used to increase the value of a variable by 1.
Example: num++; (Equivalent to num = num + 1;)
Decrement (–):
The decrement operator is used to decrease the value of a variable by 1.
Example: num–; (Equivalent to num = num - 1;)
Assignement operators
Assignment (=):
The assignment operator = is used to assign the value on the right side to the variable on the left side.
Example: int x = 10; assigns the value 10 to the variable x.
Addition Assignment (+=):
The addition assignment operator += adds the value on the right side to the variable on the left side and assigns the result to the variable.
Example: x += 5; is equivalent to x = x + 5; and increments x by 5.
Subtraction Assignment (-=):
The subtraction assignment operator -= subtracts the value on the right side from the variable on the left side and assigns the result to the variable.
Example: x -= 3; is equivalent to x = x - 3; and decrements x by 3.
Multiplication Assignment (*=):
The multiplication assignment operator *= multiplies the variable on the left side by the value on the right side and assigns the result to the variable.
Example: x *= 2; is equivalent to x = x * 2; and doubles the value of x.
Division Assignment (/=):
The division assignment operator /= divides the variable on the left side by the value on the right side and assigns the result to the variable.
Example: x /= 4; is equivalent to x = x / 4; and divides the value of x by 4.
Comparison operators
These operators return a boolean result (true or false) based on the comparison. Here are the primary comparison operators in Java:
Equal to (==):
The equal to operator == is used to check if two values or expressions are equal.
Example: if (x == y) checks if x is equal to y.
Not equal to (!=):
The not equal to operator != is used to check if two values or expressions are not equal.
Example: if (x != y) checks if x is not equal to y.
Greater than (>):
The greater than operator > is used to check if the value on the left is greater than the value on the right.
Example: if (x > y) checks if x is greater than y.
Less than (<):
The less than operator < is used to check if the value on the left is less than the value on the right.
Example: if (x < y) checks if x is less than y.
Greater than or equal to (>=):
The greater than or equal to operator >= is used to check if the value on the left is greater than or equal to the value on the right.
Example: if (x >= y) checks if x is greater than or equal to y.
Less than or equal to (<=):
The less than or equal to operator <= is used to check if the value on the left is less than or equal to the value on the right.
Example: if (x <= y) checks if x is less than or equal to y.