Chapter3
Un article de Sometimes Kitties Think Too.
[modifier]
Chapter 3 - Operators & Assignments
[modifier]
Stack & Heap
+ instance (objects) variables live on heap
+ local variables live on stack
[modifier]
Literals
+ a source code representation for a value of a string object
+ arrays are the only non-primitive type that have a literal representation
+ all integer literals may be proceeded by a 'L' at the end
--decimal - base10
--hexadecimal - base16, a preceeding '0x' is required
--octal - contain only 0-7, begins with a '0' (up to 21 digits n.i. 0)
e.g. int oct = 0231;
--floating Point Literal
+ every floating point is implicitly a double(64 bit)
+ compiler won't allow a floating point number to be assigned to a "float" w/o explicit cast
+ no need for a explicit cast for doubles ('D') because it is the default behavior
--character (unsigned 16 bit representation)
+ represented by a single character in quotes or the Unicode in quotes
or an integer with a cast
[modifier]
Assignment
+ e.g. of an implicit cast (widening conversion): double d = 100D;
+ bytes, shorts, chars, when assigned a larger literal, will be implicitly cast down
+ 2 bytes, if added together will be int sized because of the implicit cast. Therefore
byte c = a + b; <---- illegal (where a,b are bytes) int c = a + b; <---- correct |
+ can assign a subclass of the declared type (but not superclass)
Bar b = new Foo(); // where Bar extends Foo <---- illegal
Foo f = new Bar(); // where Bar extends Foo <---- correct
|
e.g. Foo f = new Bar(); // where Bar extends Foo
variable - bit holder
reference variable - bit of an address for how to get to the object
primitive - value is equivalent to a number
+ narrowing requires an explicit cast
e.g.
float f = 100F;
int i = (int) 1222222;
|
+ when there is a loss of precision by casting, only the most significant left-most bits are used
byte b = (byte) 128;
since 128 is a 32 bit int, the leftmost 24 bits are removed
and 10000000 is left. 2's complement notation means that
the bits are flipped and then 1 is added.
resulting in -128
+ need explicit casting when there is a loss of precision.
e.g.
byte b = 0x3;
b =+ 1; ----should be----> b = (byte) (b + 1)
|
[modifier]
Conversion of Primatives
+ an automatic conversion will happen in the following scenarios:
- Assignment
% A non-boolean may be converted to another non-boolean type, provided the conversion is a widening conversion.
% A non-boolean MAY NOT be converted to another non-boolean type, if the conversion would be a narrowing conversion.
% A boolean MAY NOT be converted to any other type.
- Method call (Implicit casting)
- a method will accept any argument that's narrower than the signature parameter
- Arithmetic promotion
% All arithmetic expressions are promoted to the wider of the operands.
% The promotion is at least to int, even if no int operand appears.
% these rules don't apply to "++" and "--"
- Explicit casting
- can widen or narrow (except for boolean)
[modifier]
Equality
+ .equals()
will return false even for Wrapper classes that look like they have the same value.
Why?
Because the equals() method does a instanceof test
| ObjectA | WrapperA | primitive | |
|---|---|---|---|
| ObjectB | IS-A ?? | false | false |
| WrapperB | false | false | maybe |
| primitive | false | maybe | compiler error |
+ ==
this compares references. Is the reference to the same object?
Compiler error will result if the objects being compared are different
However, if a primitive and wrapper class are being compared, autoboxing will allow
the comparison to go forward
== will return true when a wrapper object and a primitive have the same values
(Boolean, Byte, Character, Short, Integer) because one will be unboxed
+ == special cases (See Below)
When Wrapper classes wrap primitives that are not immutable, then equality doesn't hold true
[modifier]
Rounding
+ integer arithmetic operations are floored, so 9/10 is floored to 0 + printf() rounds numbers in the normal way
[modifier]
Scope
+ static variables have longest scope and last as long as the class is loaded
+ instance variables last as long as instance lives
[modifier]
Unitialized Variables
+ local variables (stack) have no default initialization
+ instance variables get default initialization values
variable type | default value
------------------------------------------------------
object | null
byte, short |
long, int | 0
float, double | 0.0
boolean | false
char | '\u0000'
+ array elements are ALWAYS given default values
[modifier]
Automatic Variables
+ automatics are local variables
+ unitialized local primatives will result in a compiler error
+ local references are NOT default initialized (to null)
+ Java is pass-by-value (for all variables running within a single VM)
- an object's reference is passed with copy of the reference bits
- a primative is passed with the a copy of the value of the primative
[modifier]
Arrays
+ are objects that store multiple variables of the same type
+ arrays live on the heap
+ arrays can be declared, constructed and initialized
+ array constructors need to specify a size.
however, this is legal:
int[][] example = new int[3][];
+ negative numbers not allowed in array indices and the numbering starts at '0'
+ ArrayIndexOutOfBoundsException is a >>runtime<< exception
+ single public variable, "length"
+ anonymous arrays --> int[][] anonArray = { {1,2,3}, {3,4,5}, {5,6,7} };
because the middle arrays have no reference variables
+ primitive arrays can hold any type that can be implicitly promoted to the
declared type of the array , e.g. a int[] can hold shorts, char, ints
+ arrays of object references can contain subclass or interface of array type
arrays of interfaces can contain IS-A classes, or implementors of the interface
+ primitive arrays cannot be reassigned to other reference types other than what the array contains
int[] this = new int[3];
char[] that = this; <--illegal
+ not so restrictive with arrays of objects.
+ interface reference can be assigned to an array of objects implementing that interface
[modifier]
Initialization Blocks
+ there exist static and instance initialization blocks
+ they run when a class or instance is initialized and after all super-constructors have run
+ don't take arguments and don't return anything
+ they run in the order they appear
[modifier]
Wrapper Classes & Boxing
+ there is a wrapper class for every Java primitive
+ most wrapper classes (except Character) take String as a constructor arg
which throws NumberFormatException if there's a problem
+ Boolean wrapper will be false unless either a true (boolean value)
or "true" (String) are used in the constructor argument...
wrapper classes:
java.lang.Boolean
java.lang.Character
java.lang.Long
java.lang.Float
java.lang.Integer
java.lang.Double
java.lang.Byte
java.lang.Short
XXX valueOf(String s)
STATIC
+ second method to constructing a wrapper class.
Takes String argument and radix (base)
xxx parseXXX(String s)
STATIC
+ static method, throws NumberFormatException
+ returns named primative. e.g. Double.parseDouble("3.12") --> double
String toString(XXX)
STATIC
+ returns string of the primative that's wrapped.
Long and Integer have a static toString( base10, radix)
xxx xxxValue()
+ converts wrapped numeric to primative e.g. short f = f2.shortValue();
static instance method
[modifier]
Autoboxing
+ compiler automatically unboxes and unwraps the object reference (in the process creating a new wrapper)
+ == and != do not act the same
!= works as expected
+ == will return true when a wrapper object and a primitive have the same values
(Boolean, Byte, Character, Short, Integer and Long) and are of same type (no widening)
because one will be unboxed
+ equals() returns false when comparing between differnt Wrappers (Even if the same primitive value)
+ BUT equals() will return true if comparing the same primitive value.
e.g.
int i = 10;
Integer II = new Integer(10);
II.equals(i); ---> true
+ NullPointerExceptions can happen with wrapper objects
[modifier]
Overloading
widening - for example expanding a byte to fit a int argument
+ JVM uses the method with the narrowest argument type that's wider than the parameter
+ widening takes precedence over boxing (because of pre-Java5 code)
+ widening takes precedence over var-args
+ auto-boxing takes precedence over var-args
[modifier]
Widening Reference Variables
+ is legal to widen the parameter supplied to a method, as long as it passes the IS-A test
because the parameter will only be asked to do the superclass things within the method
+ cannot widen between wrappers, e.g. Integer cannot fit into a Long's place
+ can only box-then-widen NOT widen-then-box
Precedence
-----------------------------
(highest) ^ widen
| ^
| auto-box
| ^
(lowest) | var-args
[modifier]
Garbage Collection
+ JVM decides when it is run
+ can request it by calling System.gc
+ GC run in low priority daemon thread
+ no guarantee on implementation, platform specific
+ all non-String objects are eligible for collection when no live thread can access it
+ garbage collecting is performed by Runtime class
Runtime.getRuntime() ---> Singleton
Runtime.getRuntime().gc()
[modifier]
Making objects Eligible for Garbage Collection
+ once a reference is assigned a null value it is eligible for collection
+ local variables can be GC once the method has completed
+ if a ref variable is reassigned, the old object is eligible for GC
+ Exceptions thrown in the finalize() method are ignored by the GC
+ finalize() can be used to free up other resources besides memory. Like files, network connections
+ Object's finalize() throws an Exception
[modifier]
Special Behavior
Normally, when the primitive types are boxed into the wrapper types, the JVM allocates memory and creates a new object. But for some special cases, the JVM reuses the same object.
The following is the list of primitives stored as immutable objects:
- boolean values true and false
- All byte values
- short values between -128 and 127
- int values between -128 and 127
- char in the range \u0000 to \u007F
so.........
Integer small1 = 20; Integer small2 = 20; small1 == small2 ? -----> true
whereas.....
Integer big1 = 200; Integer big2 = 200; big1 == big2 ? -----> false
Note: this special behavior only applies to Wrapper classes and '=='!
[modifier]
Question
1. When you initialize an object manually or by default to null, does that mean it's eligible for GC? 2. Does auto-boxing imply both directions 3. what's an example of box-then-widen that doesn't violate widening between wrappers
