Chapter 1 Language Fundamentals
Chapter 1 Language Fundamentals
13. All numeric data types are signed. char is the only unsigned integral type.
14. Object reference variables are initialized to null.
15. Octal literals begin with zero. Hex literals begin with 0X or 0x.
16. Char literals are single quoted characters or unicode values (begin with \u).
17. A number is by default an int literal, a decimal number is by default a double literal.
18. 1E-5d is a valid double literal, E2d is not (since it starts with a letter, compiler thinks that it’s an identifier)
19. Two types of variables.
1. Member variables
Accessible anywhere in the class.
Automatically initialized before invoking any constructor.
Static variables are initialized at class load time.
Can have the same name as the class.
2. Automatic variables(method local)
Must be initialized explicitly. (Or, compiler will catch it.) Object references can be initialized to null to
make the compiler happy. The following code won’t compile. Specify else part or initialize the local
variable explicitly.
Member Color
Instance method Red
Static method Green
Final variable Blue
Constructor Yellow
Chapter 2 Operators and assignments
1. Unary operators.
1.1 Increment and Decrement operators ++ --
We have postfix and prefix notation. In post-fix notation value of the variable/expression is modified
after the value is taken for the execution of statement. In prefix notation, value of the
variable/expression is modified before the value is taken for the execution of statement.
9. General
In Java, No overflow or underflow of integers happens. i.e. The values wrap around. Adding 1 to the
maximum int value results in the minimum value.
Always keep in mind that operands are evaluated from left to right, and the operations are executed in the
order of precedence and associativity.
Unary Postfix operators and all binary operators (except assignment operators) have left to right
assoiciativity.
All unary operators (except postfix operators), assignment operators, ternary operator, object creation and
cast operators have right to left assoiciativity.
Inspect the following code.
public class Precedence {
final public static void main(String args[]) {
int i = 0;
i = i++;
i = i++;
i = i++;
System.out.println(i); // prints 0, since = operator has the lowest
precedence.
1. Modifiers are Java keywords that provide information to compiler about the nature of the code, data and classes.
2. Access modifiers – public, protected, private
Only applied to class level variables. Method variables are visible only inside the method.
Can be applied to class itself (only to inner classes declared at class level, no such thing as protected or
private top level class)
Can be applied to methods and constructors.
If a class is accessible, it doesn’t mean, the members are also accessible. Members’ accessibility determines
what is accessible and what is not. But if the class is not accessible, the members are not accessible, even
though they are declared public.
If no access modifier is specified, then the accessibility is default package visibility. All classes in the same
package can access the feature. It’s called as friendly access. But friendly is not a Java keyword. Same
directory is same package in Java’s consideration.
‘private’ means only the class can access it, not even sub-classes. So, it’ll cause access denial to a sub-
class’s own variable/method.
These modifiers dictate, which classes can access the features. An instance of a class can access the private
features of another instance of the same class.
‘protected’ means all classes in the same package (like default) and sub-classes in any package can access
the features. But a subclass in another package can access the protected members in the super-class via only
the references of subclass or its subclasses. A subclass in the same package doesn’t have this restriction.
This ensures that classes from other packages are accessing only the members that are part of their
inheritance hierarchy.
Methods cannot be overridden to be more private. Only the direction shown in following figure is permitted
from parent classes to sub-classes.
3. final
final features cannot be changed.
final classes cannot be sub-classed.
final variables cannot be changed. (Either a value has to be specified at declaration or an assignment
statement can appear only once).
final methods cannot be overridden.
Method arguments marked final are read-only. Compiler error, if trying to assign values to final arguments
inside the method.
Member variables marked final are not initialized by default. They have to be explicitly assigned a value at
declaration or in an initializer block. Static finals must be assigned to a value in a static initializer block,
instance finals must be assigned a value in an instance initializer or in every constructor. Otherwise the
compiler will complain.
Final variables that are not assigned a value at the declaration and method arguments that are marked final
are called blank final variables. They can be assigned a value at most once.
Local variables can be declared final as well.
4. abstract
Can be applied to classes and methods.
For deferring implementation to sub-classes.
Opposite of final, final can’t be sub-classed, abstract must be sub-classed.
A class should be declared abstract,
1. if it has any abstract methods.
2. if it doesn’t provide implementation to any of the abstract methods it inherited
3. if it doesn’t provide implementation to any of the methods in an interface that it says implementing.
Just terminate the abstract method signature with a ‘;’, curly braces will give a compiler error.
A class can be abstract even if it doesn’t have any abstract methods.
5. static
Can be applied to nested classes, methods, variables, free floating code-block (static initializer)
Static variables are initialized at class load time. A class has only one copy of these variables.
Static methods can access only static variables. (They have no this)
Access by class name is a recommended way to access static methods/variables.
Static initializer code is run at class load time.
Static methods may not be overridden to be non-static.
Non-static methods may not be overridden to be static.
Abstract methods may not be static.
Local variables cannot be declared as static.
Actually, static methods are not participating in the usual overriding mechanism of invoking the methods
based on the class of the object at runtime. Static method binding is done at compile time, so the method to
be invoked is determined by the type of reference variable rather than the actual type of the object it holds
at runtime.
Let’s say a sub-class has a static method which ‘overrides’ a static method in a parent class. If you have a
reference variable of parent class type and you assign a child class object to that variable and invoke the
static method, the method invoked will be the parent class method, not the child class method. The
following code explains this.
p = c;
p.doStuff(); // This will invoke Parent.doStuff(), rather than
Child.doStuff()
}
}
class Parent {
static int x = 100;
public static void doStuff() {
System.out.println("In Parent..doStuff");
System.out.println(x);
}
}
Modifier Class Inner classes Variable Method Constructor Free floating Code block
(Except local and
anonymous
classes)
public Y Y Y Y Y N
protected N Y Y Y Y N
(friendly) Y Y (OK for all) Y Y Y N
No access
modifier
private N Y Y Y Y N
final Y Y (Except Y Y N N
anonymous
classes)
abstract Y Y (Except N Y N N
anonymous
classes)
static N Y Y Y N Y (static initializer)
native N N N Y N N
transient N N Y N N N
synchronized N N N Y N Y (part of method, also
need to specify an
object on which a lock
should be obtained)
volatile N N Y N N N
Chapter 4 Converting and Casting
Unary Numeric Promotion
Contexts:
Operand of the unary arithmetic operators + and –
Operand of the unary integer bit-wise complement operator ~
During array creation, for example new int[x], where the dimension expression x must evaluate to an
int value.
Indexing array elements, for example table[‘a’], where the index expression must evaluate to an int
value.
Individual operands of the shift operators.
Conversion of Primitives
1. 3 types of conversion – assignment conversion, method call conversion and arithmetic promotion
2. boolean may not be converted to/from any non-boolean type.
3. Widening conversions accepted. Narrowing conversions rejected.
4. byte, short can’t be converted to char and vice versa.
5. Arithmetic promotion
5.1 Unary operators
if the operand is byte, short or char {
convert it to int;
}
else {
do nothing; no conversion needed;
}
5.2 Binary operators
if one operand is double {
all double; convert the other operand to double;
}
else if one operand is float {
all float; convert the other operand to float;
}
else if one operand is long {
all long; convert the other operand to long;
}
else {
all int; convert all to int;
}
6. When assigning a literal value to a variable, the range of the variable’s data type is checked against the value of
the literal and assignment is allowed or compiler will produce an error.
char c = 3; // this will compile, even though a numeric literal is by default an int since the range of char
will accept the value
int a = 3;
char d = a; // this won’t compile, since we’re assigning an int to char
char e = -1; // this also won’t compile, since the value is not in the range of char
float f = 1.3; // this won’t compile, even though the value is within float range. Here range is not
important, but precision is. 1.3 is by default a double, so a specific cast or f = 1.3f will work.
float f = 1/3; // this will compile, since RHS evaluates to an int.
Float f = 1.0 / 3.0; // this won’t compile, since RHS evaluates to a double.
7. Also when assigning a final variable to a variable, even if the final variable’s data type is wider than the
variable, if the value is within the range of the variable an implicit conversion is done.
byte b;
final int a = 10;
b = a; // Legal, since value of ‘a’ is determinable and within range of b
final int x = a;
b = x; // Legal, since value of ‘x’ is determinable and within range of b
int y;
final int z = y;
b = z; // Illegal, since value of ‘z’ is not determinable
8. Method call conversions always look for the exact data type or a wider one in the method signatures. They will
not do narrowing conversions to resolve methods, instead we will get a compile error.
Casting of Primitives
9. Needed with narrowing conversions. Use with care – radical information loss. Also can be used with widening
conversions, to improve the clarity of the code.
10. Can cast any non-boolean type to another non-boolean type.
11. Cannot cast a boolean or to a boolean type.
Compile-time Rules
When old and new types are classes, one class must be the sub-class of the other.
When old and new types are arrays, both must contain reference types and it must be legal to cast
between those types (primitive arrays cannot be cast, conversion possible only between same type of
primitive arrays).
We can always cast between an interface and a non-final object.
Run-time rules
If new type is a class, the class of the expression being converted must be new type or extend new
type.
If new type is an interface, the class of the expression being converted must implement the interface.