Friday, March 30, 2007

CONVERSIONS AND PROMOTIONS

CONVERSIONS AND PROMOTIONS

INTRODUCTION:
Type conversion is a facility in the java programming language whereby expressions whose type is not appropriately specified in a context can be implicitly converted from the type specified by the programmer to a type acceptable for its surrounding context.

A specific type conversion can also be asked for by a programmer. There is need for this in some cases:
a. to cause the java machine at run-time[1] to check for the validity of the conversion.
b. to cause a translation of the run-time value of the expression into a form appropriate for the new type.

The possible set of specific conversions in the java programming language are grouped into several broad categories:
- identity conversion
- widening primitive conversion
- narrowing primitive conversion
- widening reference conversion
- narrowing reference conversion
- boxing conversion
- unboxing conversion
- capture conversion
- String conversion
- Value set conversion

There are in addition 5 conversion contexts in which the conversion of expressions may occur. Each context allows conversion in some categories noted above but not in others.

Note that the term “conversion” is also used to describe the process of choosing a specific conversion for such a context. The 5 conversion contexts are:
- Assignment conversion: converts the type of an expression to the type of a specified variable.
- Method invocation conversion: this is applied to each argument in a method or constructor invocation and except in one case, performs the same conversion that assignment conversion does.
- Casting conversion: converts the type of an expression to the type explicitly specified by a cast operator
- String conversion: allows any type to be converted to type String
- Numeric promotion: brings the operands of a numeric operator to a common type so that ann operation can be performed.

(§5.1 of the jls has an example for the conversions above that I do not want to repeat. You can get it and study. )

Footers:

[1]. A run-time type refers to the classes of the object referred to by the value of the variable or expression at run-time, assuming that the value is not null.

TYPES, VALUES AND VARIABLES(11)

TYPES, VALUES AND VARIABLES(11)

KINDS OF VARIABLES:
6. Exception handler parameter: an exception handler parameter is created each time an exception is caught by the catch clause of a try statement. The new variable is initialized with the actual object associated with the exception. The exception handler parameter ceases to exist when execution of the block associated with the catch clause is complete.

public class ExceptionHandler {
String name;

void writeName(String typed){

try{
name = typed;
}
//exception handler created here. variable of
//type NumberFormatException
catch (NumberFormatException n){
System.out.println("Wrong entry, please.");
}
}
}

7. Local Variable: is declared by a local variable declaration statement. When the flow of control enters a block or for statement, a new variable is created for each local variable declared in a local variable declaration statement immediately contained in a block or for statement.

A local variable declaration statement may contain an expression which initializes the variable. The local variable with an initializing expression is not initialized however until the local variable declaration statement that declares it is executed. The local variable effectively ceases to exist when the execution of the block or for statement is complete.

public class ArrayComponents {
//an array of integers as components
int[] five = new int[5];

//this method takes all the default values
//according to jls, 0 and prints them out.
void defaultvalue(){ //local variable declaration block
for (int i=0;i<5;i++ ){ //new variable i, for statement
System.out.print("The ");
switch(i){
case(0): System.out.print("first ");break;
case(1): System.out.print("second ");break;
case(2): System.out.print("third ");break;
case(3): System.out.print("fourth ");break;
case(4): System.out.print("fifth ");break;
default: ;break;
}
System.out.println("value is: "+five[i]);
}
}
}

Final Variables: a variable declared final may be assigned to only once. Never assign a once assigned final variable unless it has been unassigned prior to this.
A blank final is a final variable without an initializer in its declaration.
A final variable referring an object refers only to the object which returns its value. See example.
public class FinalExample {
static String bobby = "friend";
static final String drumboy = bobby; //refers to object

public static void main(String[] args){
System.out.println("Final drumboy is: "+drumboy);

//let's change the object
bobby = "enemy";

//but final will still refer to the first object
//you see why final is very useful?
System.out.print("Final drumboy after object reference change is: ");
System.out.println(drumboy);
}
}

Initial values of variables:
Every variable in a program must have a value before usage.
1. each class variable, instance variable, or array component is initialized with a default value when it is created.
- for type byte, the default is zero, (byte)0
- for type short, (short)0
- for type int, 0
- for type long, default is 0L
- for type float, default is positive zero, 0.0f
- for type double, default is positive zero, 0.0d
- for type char, the default value is the null character, i.e ‘\u0000’
2. each method parameter is initialized to the corresponding argument value provided by the invoker of the method
3. each constructor parameter is initialized to the corresponding argument value provided by a class instance creation expression or explicit constructor invocation.
4. an exception-handler parameter is initialized to the thrown object representing the exception.
5. a local variable must be explicitly given a value before use, either by initialization or assignment, in a compiler verifiable way using the rules for definite assignment.

TYPES, VALUES AND VARIABLES(10)

TYPES, VALUES AND VARIABLES(10)

Heap pollution: When the possibility exists that a variable of a parameterized type refers to an object that is not of that parameterized type. Heap pollution can only occur if the program performed some operation that would give rise to an unchecked warning at compile time.

KINDS OF VARIABLES:
There are 7 kinds of variables:
1. class variables: in a class declaration a field is declared using the keyword static ; in an interface declaration, the field can be with(out) the keyword static.
Creation of class variables: when the class or interface is prepared and then initialized to a default value.

public class ClassVar {
//primitive and reference class variables prepared
static int number;

public static void main(String[] args) {
//they are now initialised, after initialisation
//you've created a class variable
number = 24;
}
}
2. Instance variables: an instance variable is a field declared in a class declaration without the keyword static. When instance variables occur in a class are created and initialized to a default value on the creation of a new object of the class or of any class that subclasses the class. An instance variable effectively ceases to exist when the object of which it is a field is no longer referenced, after any necessary object finalization[1] has been completed.

public class InstanceVar {
//primitive and reference class variables prepared
static int number;

//an instanc variable next
boolean monkey_tail; //default is false a la jls.
}

public class Loader {
public static void main(String[] args) {
//create an object of InstanceVar
InstanceVar mine = new InstanceVar();

//you'll realise that even without initialising
//it it is given default false
System.out.println(mine.monkey_tail);

//we can still assign it though
mine.monkey_tail = true;
}
}
3. Array components: these are unnamed variables that are created and initialized to default values whenever a new object that is an array is created. The array component effectively ceases to exist when the array is no longer referenced.

public class ArrayComponents {
//an array of integers as components
int[] five = new int[5];

//this method takes all the default values
//according to jls, 0 and prints them out.
void defaultvalue(){
for (int i=0;i<5;i++ ){
System.out.print("The ");
switch(i){
case(0): System.out.print("first ");break;
case(1): System.out.print("second ");break;
case(2): System.out.print("third ");break;
case(3): System.out.print("fourth ");break;
case(4): System.out.print("fifth ");break;
default: ;break;
}
System.out.println("value is: "+five[i]);
}
}
}
public class Loader {
public static void main(String[] args) {
ArrayComponents details = new ArrayComponents();
details.defaultvalue();
}
}
4. Method parameters: method parameters name argument values passed to a method. For every parameter declaration in a method declaration, a new variable is created each time that method is invoked, which is initialized with the corresponding argument value from the method invocation. The method parameter ceases to exist when the execution of the body of the method is complete.

public class MethodExample {
String id;
int tag;

//this method takes as parameters a String name
//and an integer as number.
void setName(String name, int number){
this.id=name;
this.tag=number;
}
}
public class Loader {
public static void main(String[] args) {
MethodExample taketwo = new MethodExample();

//method invocation. this passes the required
//arguments specified by the method parameter.
taketwo.setName("adewale", 42);
}
}
5. Constructor parameters: constructor parameters name argument values passed to a constructor. Each time a class instance expression or explicit constructor invocation invokes a constructor, a new parameter variable is created and initialized with the corresponding argument value from the creation expression or constructor invocation. The constructor parameter effectively ceases to exist when the execution of the body of the constructor is complete.

public class ConstructorExamples {
String name;
int tag;

//constructor without parameters
ConstructorExamples(){
this.name="nobody";
this.tag=0;
}

//this constructor has parameters
ConstructorExamples(String up, int number){
this.name = up;
this.tag = number;
}
}
public class Loader {
public static void main(String[] args) {
//invoking the constructor without parameters
ConstructorExamples beanpole = new ConstructorExamples();

//hey, what does it contain
System.out.println("Name: "+
beanpole.name+". Number: "+beanpole.tag);

//invoking the constructor with arguments
ConstructorExamples magpie = new
ConstructorExamples("elizabeth", 3);

//you contain something too not so?
System.out.println("Name: "+magpie.name+". Number:
"+magpie.tag);
}
}

Footers:

[1]. Object finalization: freeing up resources tat cannot be freed automatically by an automatic storage manager.

TYPES, VALUES AND VARIABLES(9)

TYPES, VALUES AND VARIABLES(9)

Where types are used:
Types are used in declarations and expressions. Each of the usage below will be covered in subsequent blogs:
1. declarations:
- in imported types
- in fields
- as method parameters
- as method results (what a method returns)
- as constructor parameters
- as local variables
- as exception handler parameters
- as type variable

2. expressions
- class instance creation expressions
- generic class instance creation
- array creation
- generic method and constructor invocation
- casts
- the instanceof operator
- the arguments to parameterized types

VARIABLES:
A variable is a storage location and has an associated type, sometimes called its compile-time type, that is either a primitive type or a reference type.
All assignments to a variable are checked for assignment compatibility, usually at compile time but when involving arrays, a run-time check is made.
Variables of primitive types: these variables always hold a value of that exact primitive type.
Variables of reference types: let T be our reference type.
If T is a class type. It holds the following values:
A. a null reference e.g T var = null;
B. a reference to an instance of class T. e.g T secondvar = new T();
C. a reference to any class that is a subclass of T e.g
package api_package;

public class T {…}

public class Tsub extends T{…}

public class Loader {
public static void main(String[] args) {
T avar = new T();
Tsub anovar = new Tsub();
avar = anovar;
}
}

if T is an interface type, it can hold the following values:
a. a null reference
b. a reference to any instance that implements the interface.

public interface IT {}

public class T implements IT{}

public class Loader {
public static void main(String[] args) {
T avar = new T();
IT newvar = avar;
}
}

Note that a variable of type, array of T, T[], where
1. T is a primitive type can hold the following values:
a. a null reference
b. a reference to any array of type, T[]
public class Loader {
public static void main(String[] args) {
int[] nob = null;
int[] hope = nob;
}
}

2. T is a reference type, then a variable of type T[ ] can hold:
a. a null reference
b. a reference to any array of type, array of S, S[], such that type S is a subclass or subinterface of type T.

public class T implements IT{}

public class Tsub extends T{}

public class Loader {
public static void main(String[] args) {
T[] var = null;
var = new Tsub[1];
}
}

A variable of type Object[] can hold any array of any reference type.

A variable of type Object can hold:
a. a null reference
b. a reference to any object, whether class instance or array.

TYPES, VALUES AND VARIABLES(8)

TYPES, VALUES AND VARIABLES(8)

TYPE ERASURE:
Type erasure is a mapping from types (possibly including parameterized types and type variables) to types (that are never parameterized types or type variables). We write |T| for the erasure of a type T.
Type erasure is defined as:
- erasure of a parameterized type G as |G|
- erasure of a nested type T.C as |T|.C
- the erasure of an array type T[] as |T|[]
- the erasure of a type variable is the erasure of its leftmost bound. For example, if
T extends M implements N, then its erasure M and if
T implements N, then its erasure is N.
- erasure of every other type in the type itself.
The erasure of a method signature, m(T t) is m and erasure of T.

REIFIABLE TYPES:
Types that are completely available at run-time, after erasures, are known as reifiable types. A type is reifiable if and only if:
- it is a non-reifiable type.
- If parameterized, it has unbounded wildcard as type argument.
- It is an array type whose component type is reifiable.
- It is a raw type
- It is a primitive type

RAW TYPES:
A raw type is a parameterized type derivation to facilitate interfacing with non-generic legacy code. It is either:
a. the name of a generic type declaration less the actual type arguments i.e S has as raw type, S.
b. any non-static type member of a raw type that is not inherited from a superclass or superinterface of R.

it’s important to note the discussion in the jls for §4.8, particularly the fact that it is better to insert the complete generics for a member of a generic type or the type itself when referring to them, but in interfacing to legacy code, check your erasures very well.

INTERSECTION TYPES:
An intersection type takes the form T1 … Tn, for positive n, n>0, where each T, Ti, is defined by 1≤ i ≤n , are type expressions. Intersection types arise in the processes of capture conversion[1] and type inference[2].

Realise that intersection types are not written directly as part of a program.

Members of an intersection type:
1. a class or interface type without any member and without any inherited members from a superclass is an intersection type. Its values should be null.
2. a superclass, Ck, for a class type, T, such that Ck, has a superclass, Ci, but Ck and Ci have the same and equivalent members.
3. interfaces implemented by a class type are intersection types.

SUBTYPING:
The subtypes and supertype relations are all binary relations on types.

A direct supertype relationship is written as >1 if S is a direct supertype of T, then S >1 T.
S :> T indicates that a supertype relationship exists between S & T. S is a proper supertype of T, written S > T, if S :> T and S ≠ T.

The subtype relationship is denoted by <: . We write T <: S to denote T has a subtype relationship with S. T is a proper subtype of S, written T < S if T <: S and S ≠ T.
T is a direct subtype of S, written as T <1 S if S >1 T.

Note: subtyping does not extend through generic types: T <: U does not imply C <: C.

Subtyping among primitive types:
double >1 float
float >1 long
long >1 int
int >1 char
int >1 short
short >1 byte

Subtyping among class and interface types:
if we have a declaration like this:

Given parameterized type, C where C is defined by C , the two argument types have ranges that are subtypes of their corresponding bounds. That is T1 is bound by an upper bound, B1 and T2 by a lower bound, B2.

Given C, the direct supertype of this parameterized type are all of the following:
1. the direct superclass of the erasure of the type or C
2. the direct superinterface of C
3. the type Object, if C is an interface type with no direct superinterface (i.e it has no declaratioin of the form: implements T ).
4. the raw type, C.

package api_package;

public class Nigerian {}

//the container type or supertype of Lagosian is
//Nigerian
public class Lagosian extends Nigerian{
public static void main(String[] args){
Lagosian you = new Lagosian();

//I can cast succesfully to the supertype
System.out.println((Nigerian)you);
}
}

Given a type C its direct supertype is D if:
1. D is a direct supertype of C and theta represents each C within each “cage” of D.
Example:
package api_package;

public class Nigerian {
String name="tunde";
}
//the container type or supertype of Lagosian is
//Nigerian
public class Lagosian
extends Nigerian{
}
public class Loader {

public static void main(String[] args) {
Lagosian you = new Lagosian();

//Lagosian can access yoruba
System.out.println(you.name);
}
}
2. C is a supertype where S1 contains T1 and S2 contains T2 respectively.

The direct supertypes of an intersection type are the members of the intersection type.
The direct supertype of a type variable are the types listed in its bound.
The direct supertype of the null type are all reference types other than the null type itself.

Subtyping among Array types:
The following rules define the direct subtype relation among array types.

1. if S & T are both reference types, then
- S[] >1 T[], iff S >1 T.
- Object >1 Object[]
- Cloneable >1 Object[]
- java.io.Serializable >1 Object[]

2. if p is a primitive type, then
- Object >1 p[]
- Cloneable >1 p[]
- java.io.Serializable >1 p[]

Footers:
[1]. Capture conversion, to be discussed later, denotes a conversion of generics to their equivalent type variables taking into account the superclasses and subclasses that the type variable will have a contract with.
[2]. This is a process of inferring type arguments from method and constructor invocations.

TYPES, VALUES AND VARIABLES(7)

TYPES, VALUES AND VARIABLES(7)

This section, §4.5 needs just a little explanation and I’ve found it difficult to come up with an illustration, maybe as we go into later sections, one will spring up.

PARAMETERIZED TYPES:

A parameterized type consists of either one of a class or interface name C and an actual type argument list 1, …, TN>. A compile time error results if C is not a class or interface name.

Vector //class or interface name, Vector. Arguments: accepts Integer.

Seq> //class or interface name, Seq. arguments: a generic class, Seq which

generic class has argument, A.

What this section is saying is that type variables could end up being parameterized types if declared so and that a parameterized type could be bounded by another type which bound is called the supertype. This type and its bound has a binary relation that defines the bound, and it is a proper supertype if the parameterized type is not equal to its bounding type.

On the other hand a type variable could have a supertype but when it is declared as a parameterized type, it’s supertype is the bounding on this parameter within this section of the class or interface and not the supertype when it was declared a type variable.

Type arguments and wildcards:

Type arguments are either:

A. Reference types.

B. Wildcards, which wildcard can be bounded with the words extends or super on a reference type.

Reference types have been dealt with above.

For a wildcard type argument, , if unbounded like below:

void printCollection(Collection c){

for (Object o: c){

System.out.println(o);

}

}

Then we say the wildcard allows any kind of Collection to be used as its parameter.

According to the discussion on §4.5.1 of the jls, assuming Object for a , which is natural, is discouraged in java because:

  1. Object would be advisable to be explicitly stated if it is needed.
  2. assuming acceptability of Object will probably be invalid because Object is rarely used as an argument.
  3. the any parameter type is not enough for Object to be assumed

Features:

a. Wildcards are useful in situations when only partial knowledge about the type parameters is required.

b. wildcards may be given explicit bounds. An upper bound is signified by the syntax:

? extends B //where B is the bound

Using bounds on a wildcard is better than declaring genericity on method, if the type parameter is a method, although both methods could be used.

? super B //where B is the bound

c. 2 type arguments are provably distinct if neither of the arguments is a type variable or wildcard, and the two arguments are not the same type.

Not distinct: boolean addAll(Collection c) not distinct from boolean addAll(Collection c)

Distinct: boolean addAll(Collection c) distinct from, boolean addAll(Collection c)

TYPE ARGUMENT CONTAINMENT AND EQUIVALENCE: We’ll illustrate this using two classes, one NigerianPopulation class and LagosPopulation class. Let’s say NigerianPopulation class is defined by the numeric range i, where 10m ≤ i ≤ 130m and LagosPopulation is defined by the range j, where 3m ≤ j ≤ 5m. let’s assume that LagosPopulation is a subclass of NigerianPopulation,

Then LagosPopulation <: NigerianPopulation //LagosPopulation is a subtype of

NigerianPopulation

Where <= defines a contained in relationship

  1. ? extends LagosPopulation <= ? extends NigerianPopulation is true
  2. ? super LagosPopulation <= ? super NigerianPopulation is true
  3. LagosPopulation <= LagosPopulation
  4. LagosPopulation <= ? extends LagosPopulation
  5. LagosPopulation <= ? super LagosPopulation

Members and constructors of parameterized types:

I’ll use just an example illustrating the notes in the jls:

package generic_example;

public class SecondGeneric {

Boolean makeBelieve = true;

String name;

//this method will be overridden

String getName(){

return name;

}

}

//the type parameters for FirstGeneric are

//String and Integer

public class FirstGeneric

extends SecondGeneric {

String name;

FirstGeneric(String thename){

this.name = thename;

}

//Note that the type of a method in this class

//corresponds to one of the type arguments of

//the class. type inference makes method genericity

//somewhat duplicative. the method's type is bound

//by the arguments that are substituting for each

//type parameter of the class. on extending

//the type of this method must be the same as the

//type of the method whose class is extended.

String getName(){

return name;

}

}

TYPES, VALUES AND VARIABLES(6)

TYPES, VALUES AND VARIABLES(6)

TYPE VARIABLES:

(Note before: this sectiont contains components that will be expanded on in later blogs. If you have questions about any statement particularly the fact that I decided to produce a skeletal illustration, feel free. )

A type variable is an unqualified identifier. They are introduced by generic class declarations, generic interface declarations, generic method declarations and generic constructor declarations[1].

Let’s think of typical declarations of type variables assuming our type variable is T and T may have superclass S and there are interfaces I1, I2.

a. where T is declaring a class.

class T extends S implements I1, I2 { }

Notes

1. a class can extend only one class, that is a class can have only one superclass otherwise compile time error.

2. extending and implementing are optional contracts T can chose to embark upon, if there is none, then superclass is Object.

3. the order of the bounds S, I1, I2 are important. A class implements only interfaces never another class.

4. if I1, I2 are parameterized types, they should not be the same erasures[2].

b. where T is declaring an interface.

Interface T extends I1, I2 { }

1. (2) above applies here.

2. (4) above also applies here.

3. an interface can extend any number of interfaces.

On the jls: the discussion on §4.4 is quite illustrative but for beginners, might be somewhat confusing, keep this for reference after parameterized types and modifiers are discussed.

Footers:

[1]. Genericity: I can best try to define genericity in this terms, as the ability of a type to define what types it can accept as parameters within its “type entity” (what I can think of here is xml’s namespace).

For example, if a house is built with the stipulation that: “N has the first flat and D has the second flat and that is how it should be”, then we can call this house generic and declare it as,

class house {} //house is the type variable.

Generics will be dwelt with in the next blog and later, we’ll discuss the scope of generics.

[2]. Erasures. Erasures are mappings from a generic type to a non-generic one. Assume a parameterized type P and P, both correspond to the same erasure |P|. Both M and P have different erasures, |M| and |P|.

Tuesday, March 27, 2007

SNIPPET: java.lang.String

SNIPPET: java.lang.String

The java.lang.String class is final. This class represents character strings. Every string is an instance of this class. Strings are constant, immutable, and the value of a String instance can’t be changed after assignment, although the values can be shared. String buffers though are mutable.

package api_package;

public class CharacterObjects {

//we'll use our char to make strings

static char[] slimman = {'Y','A','R','\'','D','U','A'};

static char[] fatman = {'A','T','I','K','U'};

public static void main(String[] args) {

//we'll use a constructor that takes array of char

String slimstring = new String(slimman);

String fatstring = new String(fatman);

//we'll play with U like before.let's pick the letter

char container = slimstring.charAt(6);

//now what did we pick?

System.out.println("We picked "+container);

//i was wrong. i forgot this is index 0.

//let's ask the all knowing machine for index

System.out.println(slimstring.indexOf("U"));//5

//so let's do it again

container = slimstring.charAt(5);

System.out.println("We picked "+container);

//let's join the two strings.

System.out.print("Joining the two strings gives ");

System.out.println(slimstring+" " + fatstring);

}

}

If there are any tips and tricks you’d like to share, do. Responses are always welcome.

SNIPPET: java.lang.Float

SNIPPET: java.lang.Float

We’ll play a little with floats here. Remember, you’ll love the language by getting worn out using it. One more exercise is not too much.

package api_package;

public class Lagosian {

static int ngozi_age = 25;

public static void main(String[] args) {

//note that this is in accord with IEEE 754

//floating point single-format bit layout.

System.out.print("Ngozi's age in floating point is: ");

System.out.println(Float.intBitsToFloat(ngozi_age));

//just to check that we are consistent

//note repetition of above methods

System.out.print("Just to be sure we're still on course:

");

System.out.println(Float.floatToRawIntBits(Float.intBitsToF

loat(ngozi_age)));

//try other exercises. you have the fundamentals to

//work with java for the maths inclined

}

}

SNIPPET: java.lang.Integer

SNIPPET: java.lang.Integer

The integer class is a final class, i.e it can’t be subclassed by any class. It’s superclass is the Number class.

The Integer class wraps the value of the primitive type int in an object and contains a single field with type int. This class has several methods for casting int to String and vice versa, as well as other useful methods for playing with int.

In the example that follows, since ages are less than 100 we’ll be working with int values that correspond to byte values. This examples assumes you already understand a little of two’s complement binary representation of numerical values.

package api_package;

public class Lagosian {

//the fields in the class

String name, sex;

int age;

//Class constructor, without parameters

Lagosian(){

this.name = "jejecy";

this.sex = "dummy";

this.age = 120;

}

//Constructor with parameters

Lagosian(String arg, String orientation, int ages){

this.name = arg;

this.sex = orientation;

this.age = ages;

}

public static void main(String[] args) {

//the first object we met in Lagos was called tunde

Lagosian firstobject = new Lagosian("tunde", "male",40);

System.out.println("Tunde: My name is "+

firstobject.name+".");

//The second was a woman, Ngozi

Lagosian secondobject = new Lagosian("ngozi","female",25);

System.out.println("Ngozi: My name is "+secondobject.name);

//we met a third person who looked like lagbaja

Lagosian thirdperson = new Lagosian();

System.out.println("What is the name of the third

person?");

System.out.println("I answered: his name is

"+thirdperson.name+" and i think he looks like a "+thirdperson.sex);

//we'll be working with the interger values from here

//let's take Ngozi's age. What's the two's complement

//binary representation? 11001

System.out.print("Ngozi's age in binary is: ");

System.out.println(Integer.toBinaryString(secondobject.age)

);

//the bits that are on are 3. that's the population

//count.

System.out.print("The population count is: ");

System.out.print(Integer.bitCount(secondobject.age));

System.out.print(". Which as a double is written as: ");

System.out.println(((Integer)secondobject.age).doubleValue(

));

//A little on bits. What is the highest bit on? 2 raised 4.

System.out.print("The highest one bit is: ");

System.out.print(Integer.highestOneBit(secondobject.age));

System.out.print(". While the lowest is: "); //2 raised 0

System.out.println(Integer.lowestOneBit(secondobject.age));

//concept of leading zeros. remember int is 32 bits.

System.out.print("The leading zeros which you didn't see

are: ");

System.out.println(Integer.numberOfLeadingZeros(secondobjec

t.age));

//reversing the bits and then Ngozi will be a Pterosaurus

System.out.print("Reversing the bits Ngozi is now ");

System.out.println(Integer.reverse(secondobject.age)+"

years old.");

//if you know your bits and bytes, shift Ngozi's bits

//by one to the left and she becomes twice older. Does

//she like it?

System.out.print("Twice older today, Ngozi is now ");

System.out.print(Integer.rotateLeft(secondobject.age, 1)+"

years older.");

}

}

The essence of the exercises are that by doing you’ll get used to the java environment and you’ll be confident of exploring new ways of using the language.