Back to Basics – Subtler Nuances – Part Two

FinalReferenceInitializer.java

public class FinalReferenceInitializer {
	static String staticVar;

	public FinalReferenceInitializer() {
		initializeFinalVar();
		staticVar = "new Value for static var";
		System.out.println(staticVar);
	}

	public static void initializeFinalVar() {
		staticVar = new String("Static var Initializes");
		System.out.println(staticVar);
	}

	public static void main(String args[]) {
		FinalReferenceInitializer fri = new FinalReferenceInitializer();
		System.out.println(FinalReferenceInitializer.staticVar);
	}
}
/*
Only static variables and static methods can be called before a constructor completes.
D:\appletree>java FinalReferenceInitializer
Static var Initializes
new Value for static var
new Value for static var
*/

CallTest.java

class Factory {
	{
		System.out.println("A1");// 7 - instance init blocks run - right after
									// call to super()
	}
	static {// 1 static block executes - when Factory class is loaded - first
			// one to do so
		System.out.println("A9");// 1.a
	}

	public Factory() {// 6 default constructor called - which calls super()
		System.out.println("A2");// 8
	}
};

class CementFactory extends Factory {
	{
		System.out.println("A8");// 9 - instance init blocks run right after
									// call to super()
	}
	static {// 2 static block executes - when CementFactory class is loaded
			// -second to do so
		System.out.println("A3");// 2.a
	}

	public CementFactory() {// 5 default constructor called - which calls
							// super()
		System.out.println("A4");// 10
	}

	static {// 3 second static block executes in sequence- at class loading time
		System.out.println("A5");// 3.a
	}
};

class MyCementFactory extends CementFactory {
	public static void main(String args[]) {
		System.out.println("A6");// 4 first line in main executed after class is
									// loaded
		new MyCementFactory();// calls default constructor which in turn calls
								// super()
		System.out.println("A7");// 9
	}
};
/**
D:\appletree>java MyCementFactory
A9
A3
A5
A6
A1
A2
A8
A4
A7
**/

WidenTest.java

public class WidenTest {
	static void overload(int x) {
		System.out.println("Integer");
	}

	static void overload(float x) {
		System.out.println("float");
	}

	public static void main(String[] args) {
		byte b = 5;
		overload(b);
	}
}

/**
When an exact match is not found in an overloaded the smallest arg that is wider than the parameter is selected

D:\appletree>java WidenTest
Integer
*/

NarrowTest.java

public class NarrowTest {
	static void overload(byte x) {
		System.out.println("Integer");
	}

	static void overload(short x) {
		System.out.println("float");
	}

	public static void main(String[] args) {
		int b = 5;
		overload(b);
	}
}
/**

D:\appletree>javac NarrowTest.java
NarrowTest.java:12: cannot find symbol
symbol  : method overload(int)
location: class NarrowTest
overload(b);
^
1 error
*/

BoxTest.java

public class BoxTest {
	static void overload(Integer x) {
		System.out.println("Boxed");
	}

	static void overload(long x) {
		System.out.println("Widened");
	}

	public static void main(String[] args) {
		int b = 5;
		overload(b);
	}
}

/**
Widening beats auto boxing
reason -> widening existed prior to java 5 and hence backward compatibility is supported
D:\appletree>java BoxTest
Widened
*/

VarArgTest1.java

public class VarArgTest1 {
	static void overload(int x, int y) {
		System.out.println("Backward compatible");
	}

	static void overload(int... x) {
		System.out.println("Var arg");
	}

	public static void main(String[] args) {
		int b = 5;
		int c = 7;
		overload(b, c);
	}
}

/**
Method call is now backward compatible!
D:\appletree>java VarArgTest1
Backward compatible
*/

VarArgTest2.java

public class VarArgTest2 {
	static void overload(float x, float y) {
		System.out.println("Backward compatible");
	}

	static void overload(int... x) {
		System.out.println("Var arg");
	}

	public static void main(String[] args) {
		int b = 5;
		int c = 7;
		overload(b, c);
	}
}
/**
Method call is now backward compatible!
Widening beats var args
D:\appletree>java VarArgTest2
Backward compatible
*/

AutoBoxingVsVarArgs.java

public class AutoBoxingVsVarArgs {
	static void overload(Integer x, Integer y) {
		System.out.println("Boxed");
	}

	static void overload(int... x) {
		System.out.println("Var Arg");
	}

	public static void main(String[] args) {
		int b = 5;
		int c = 6;
		overload(b);
		overload(b, c);
	}
}

/**
var args are catch all arguments and have the lowest precedence

D:\appletree>java AutoBoxingVsVarArgs
Var Arg
Boxed
*/

WrapperWidening.java

class WrapperWidening {
	void widenWrapper(Integer y) {
		System.out.println("Accepted?");
	}

	public static void main(String[] args) {
		Short x = new Short(2 + "");
		widenWrapper(x);
	}
}
/**
D:\appletree>javac WrapperWidening.java
WrapperWidening.java:9: widenWrapper(java.lang.Integer) in WrapperWidening cannot be applied to (java.lang.Short)
widenWrapper(x);
^
1 error
*/

ArrayWidening.java

class ArrayWidening {
	void widenArray(int[] c) {
		System.out.println("Accepted?");
	}

	public static void main(String[] args) {
		byte[] b = new byte[2];
		widenArray(b);
	}
}
/**
D:\appletree>javac ArrayWidening.java
ArrayWidening.java:9: widenArray(int[]) in ArrayWidening cannot be applied to (byte[])
widenArray(b);
^
1 error
*/

BoxAndWiden.java

class BoxAndWiden {
	void boxAndWiden(Integer z) {
		System.out.println("Accepted?");
	}

	public static void main(String[] args) {
		short c = 4;
		boxAndWiden(c);
	}
}
/**
Fails because short would be boxed to Short but Short cannot be widened to Integer

D:\appletree>javac BoxAndWiden.java
BoxAndWiden.java:9: boxAndWiden(java.lang.Integer) in BoxAndWiden cannot be applied to (short)
boxAndWiden(c);
^
1 error
*/

WidenBox.java


class WidenBox {
	public static void main(String[] args) {
		int c = 1;
		boxInteger(c);
		widenBox(c);
		boxVarArg(c, c);
		widenVarArg(c, c);
	}

	static void boxInteger(Integer i) {// making this any other Wrapper type
										// won't work
		System.out.println(i.intValue());
	}

	static void widenBox(Object o) {
		Integer i = (Integer) o;
		System.out.println(i.intValue());
	}

	static void boxVarArg(Integer... i) {// making this any other Wrapper type
											// won't work
		System.out.println("int boxed to Integer and var-arged");
	}

	static void widenVarArg(long... i) {
		System.out.println("int widened to long and var-arged");
	}
}
/**
int c is boxed to Integer
int c is boxed to Integer, Integer widened to Object
int c is boxed and assigned to var arg
int c is widened and assigned to var arg

D:\appletree>java WidenBox
1
1
int boxed to Integer and var-arged
int widened to long and var-arged

*/

About cuppajavamattiz
Matty Jacob - Avid technical blogger with interests in J2EE, Web Application Servers, Web frameworks, Open source libraries, Relational Databases, Web Services, Source control repositories, ETL, IDE Tools and related technologies.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: