/** Sandeep Desai s_desai@hotmail.com http://www.thedesai.net Fundamentals.java Show all the basic features of Java such as using scalars, arrays, control structures, strings, assert You can print this program and read it from top to bottom Book Reference: Thinking in Java 3rd Ed Sun Certified Java Programmer by Kathy Sierra and Bert Bates To run this program download the J2SDK 1.4.2 or later from java.sun.com cd \j2sdk1.4.2_05\bin javac Fundamentals.java set classpath=. java Fundamentals restrictive -> less private <default> protected public valid identifiers (variable names) start with letters can have $ _ and digits transient volatile for variables only && || only work with booleans & | ^ works with int and boolean Watch for variables with public access byte b = (byte) 9 + 500; // precision loss error adding byte to int Note difference between array.length and String.length() instanceOf is not the same as instanceof An assignment statement which looks like a comparison if( a=true)... if System.exit() in try-catch-finally blocks then finally not executed Uninitialized variable references with no path of proper initialization. -0.0 == 0.0 is true. continue must be in a loop( for, do , while ). not in case constructs. Forward references to variables gives compiler error. Primitive array types of different types can never be assigned to each other == gives compiler error if the operands are cast-incompatible. compiler errors for statement after break or return as unreachable protected void finalize() throws Throwable char promoted to int but int not promoted to char Compiler should see path where final variable initialized (similar to local variable usage) String s, StringBuffer sb; if (s==sb) compile time error if (true ^ false) compiles static methods can be protected String, StringBuffer, System, Math, Wrapper classes are final String, Wrappers immutable Math not object so not immutable ~3 == -4 loop: int x=0; for(..) if () break loop; // compilation error */ // optional but has to be first line, namespace to // resolve conflicts java converts . to directories //package foo; // use internet domain in reverse to guarantee uniqueness // package com.mydomain.test /** Reserved keywords abstract boolean break byte case catch char class const continue default do double else extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch syncrhonized this throw throws transient try void volatile while assert Note const and goto unused reserved keywords */ /** Note assignment left to right x = 0; a[y] = ++y; // update a[0] and not a[1] Operator precedence Mnemonic Operator Type Operators Ulcer Unary + - ++ -- Addicts Arithmetic and Shift * / % + - << >> Really Relational > < <= >= == != Like Logical and bitwise && || & | ^ C Conditional (ternary) a > b ? c : d A lot Assignment = += *= %= /= */ // All the comments below are picked up the javadoc tool and are used // for generating documentation, it generates // cross-referenced HTML pages // All the @ tags tell javadoc markers /** * Javadoc is a way to document code * Embedd <em>html</em> * @author author info * @see classname * @see fully-qualified-classname#method-name * @since * @version * @throws class-name descriptions exceptions thrown by class or method * @deprecated cause Java compiler warnings that this class or method may * be removed * {@docRoot} * {@inheritDoc} * method specific javadoc are @throws, @deprecated @param and @return * @param parameter-name description * @return description **/ public class Fundamentals { // public static means a function accessible from anywhere (global function) // narrow to widest byte short int long float double public static void primitives() { // Primitive data types all data types are signed, // no unsigned data type except char boolean ab1; // Initialize to false can be true or false boolean ab2 = true; boolean ab3, ab4; char ac = 'a'; // 16-bit Unicode range 0 to 2^16-1 char ac2 = '\uaaaf'; // Unicode hex 32-bit character byte ab = 2; // 8-bit range -128 to +128 ab = (byte)257; // ab becomes 1 as overflow is 257 % 256 (range of byte) short as1 = 5; // 16-bit range 2^15-1 +2^15+1 (-32768 to 32767) short as2 = 6; // without typecast compilation error about loss of precision short as3 = (short) (as1 + as2); as2 += as1; // OK int ai1 = 1; // range -2^31 to +2^31 (-2147483648 to 214783467) int ai2; // Initialized to zero int ai3 = 0x2f; // Hexadecimal (lowercase) int ai4 = 0X2F; // Hexadecimal (uppercase) int ai5 = 0177; // Octal (leading zero) int ai6 = 'c'; // Valid int ai7 = ai3 + ai4; // No compilation error for overflow long al = 2L; // 64-bit range -2^63 to +2^63-1 float af = 0.5f; // 32-bit // Will not compile as all fractions are double by default //float af2 = 0.3; double ad = 47e47d; // 47^47 double ae = 10e3d; // 10000 final int fi = 2; // Constant value of f cannot be changed //ai7 = fi++; // error cannot increment final int b = -2; // Negative twos complement, flip all bits and add 1 // + - * / % (modulus) ai1 = 2 + 2; ai1 = 4 * 2; ai1 += 2; // same as ai1 = ai1 + 2; int x = 17 % 4; // Result is 1 which is remainder x = -10 % 4; // Result is -2 which is remainder x = 10 % -4; // Result is 2 which is remainder ++x; // add 1 to x --x; // subtract 1 from x x = 1; x = x++; // still 1 execution left to right int y = x++; // assign first and then increment // bitwise operators work on boolean and int // & bitwise and // | bitwise or // ^ bitwise XOR (true if bits are different else false) // 1 ^ 1 is 0 and 1 ^ 0 is 1 // ~ bitwise negation // << bitwise left shift (same as mulitply by 2 to power of shift) // >> bitwise right shift (same as divide by 2 to power of shift) // >>> unsigned right shift (zero filled right shift) // Negative number are two complement -2 will be ~2 + 1 System.out.println("Hex of -2=" + Integer.toHexString(-2)); ai1 = 1; ai1 = ai1 << 1; // left shift by 1 result is 2 (always add 0 to right) ai1 = ai1 >> 33; // is ai1 >> 1 as Java does 33 % 32 ai1 = ai1 >> 32; // is do nothing ai1 = 8; // 01000 ai2 = ai1 >> 2; // result if 2 (0010) (same as ai2 = ai1 / (2^2) ai1 = 0x80000000; // 1 followed by 31 0 hex values of Integer.MIN_INTEGER ai2 = ai1 << 1; // result 0 as left shift drops the first 1 (does not wrap) ai1 = -1; ai2 = ai1 >> 1; // Number remains negative as 1 is shifted in from left ai1 = -1; ai2 = ai1 >>> 1; // Number turns positive as we shift in 0 from left System.out.println("-1 >>> 1=" + ai2); // 2147483647 ai2 = ai1 >> 34; // becomes ai2 >> 2 (34 % 32) ai2 = ai1 >> 32; // value will not change ai1 = 1; ai1 = ai1 << 31; ai1 = ai1 >> 31; System.out.println(" 31 shift " + ai1); // -1 ai1 = 5; System.out.println("bitwise negation ~5=" + ~ai1); // -6 ai2 = 3; // ternary operator ai1 = (ai2 == 3) ? 4 : 5; // if true set ai1 to 4 else 5 ai1 = (int) 4.3; // ai1 will be 4 ai1 = Integer.MIN_VALUE; int bi1 = -ai1; // value is Integer.MIN_VALUE because of overflow long l = 130L; // result is -126 as left most bits beyond 8th bit are trimmed short s = (short) l; long al5 = ai1; // implicit cast widening // explicit cast required because of possible loss of precision ai1 = (int) al5; //byte b = (byte) 9 + 500; // compile error b = (byte)( 9 + 500); // OK int c = 0; try { int d = 3 / c; } catch (ArithmeticException e) { System.out.println("Runtime exception " + e); } try { int d = 3 % c; } catch (ArithmeticException e) { } float afz = 3f / 0; // No exception // Note && is short circuited so if first part is false, // it does not evaulate 3/0 // hence no runtime error boolean b5 = ((3 < 2) && (1 < (3 / 0))); // since first part true don't evaluate second part b5 = ((3 > 2) || (1 < (3 / 0))); // Note here both b7 and b8 evaluated //divide by zero exception thrown try { boolean b9 = true | (1 < 3/ 0); } catch (ArithmeticException e) { System.out.println("/ by zero because of |");} // logical operators && || ! boolean b2 = ai1 > 0 && ai1 < 5; // b2 = ~b2; //compilation fails b2 =!b2; // runs } // Java checks that an array index is in range, if not it reports an error // Array is an instanceof Object public static void arrays() { // void means returns nothing // Array of 3 elements with all elements initialized to zero int[] afoo1 = new int[3]; Object o = afoo1; // Array is an object int [] a,b; // both a and b arrays int c[],d; // a[] array and b is int // Array of 2 elements afoo2.length returns the length of an array int[] afoo2 = { 3, 5 }; // **** int[2] = {4, 5} compilation error // Java will report index out of range error (throw exception) //afoo2[3] = 1; int[] bref = afoo1; // bref points to afoo1 int[][] a1 = { { 1, 2, 3}, {4, 5, 6} }; // 2 Dimensional array short[] ashort3; //ashort3 = afoo1; // compilatin error incompatible types int[] and short[] afoo2[0] = 4; // class Car {} class Honda extends Car // Honda[] h; Car[] c = h; // OK // h = c; // compile error if (afoo2 instanceof Object) System.out.println("int[] instanceof object"); // afoo2.length is array length System.out.println("afoo2 length " + afoo2.length); int p[] = { 4,5}; int q = 1; p[q] = q = 0; // p[1] = 0, q = 0 // evaluated left to right int[] ia = null; char[] ca = null; // Cannot cast primitive array from type to another //ia = (int[]) ca; // will not compile } /** String is not a primitive datatype it is a full fledged Java Object String is immutable, once set cannot be modified, have to create new String objects String class is final cannot be overriden JVM tries to reuse String reference if the String data is same, hence String immutable and class final Strings stored in String constant pool so that when new String created Java checks in the String constant pool and reusesthe String String("abc") String(String orig) String(StringBuffer) String(char[] values) contentEquals(StringBuffer sb) toLowerCase() // will return the same string if no modification required boolean endsWith(String suffix) equalsIgnoreCase(String anotherString) indexOf(char) indexOf(char ch, int fromIndex) indexOf(String str) indexOf(String str, int fromIndex) lastIndexOf startsWith(String str) startsWith(String str, int offset) substring(int startIndex) substring(int startIndex, int endIndex) // endIndex count 1 from start trim() static valueOf() all primitive types static valueOf(char[] ch) static valueOf(char[] ch, int start, int end) StringBuffer final does not override equals or hashCode methods are syncrhonized StringBuffer(String s) append() // all primitive data types, String, StringBuffer, Object delete(int start, int end) insert(int offset,...) like append delete() indexOf(String str) indexOf(String str, int fromIndex) lastIndexOf(String str) lastIndexOf(String str, int fromIndex) // search backwards fromIndex replace(int start, int end, String str) setLength(int length) // truncate if less else fill with '\u0000' substring(int start) substring(int start, int end) */ public static void strings() { String sa = "Hello"; // String is not a primitive data type String sb = "Hello"; // sa == sb if (sa == sb) { } // true as Strings are stored in sa = new String("Hello"); sb = new String("Hello"); if (sa == sb) {} // false because of new sb = sa; sb = sa + " World World"; // concat string int ai = 10; // Automatic Integer to String coversion sb = sa + ai + 4; // Hello World World104 sb = sa + (ai + 4); // Hello World World14 sb = ai + 4 + sa; // 14HelloWorld // Not above + creates a new String so sa is not modified sb = sb.trim(); // trim white space String s1 = "abc"; // constructs new string internally and returns reference s1 = s1.concat("def"); // The next two statements create 3 string objects s1 = new String("abc"); s1 = s1 + sb; //****** Imutability examples s1.concat("ghi"); // Does not modify s1 s1.toUpperCase(); // Does not modify s1 s1 = s1.toUpperCase(); s1 += "z"; // same as concat //b.compareTo("Hello World"); // used for sorting boolean b = sb.equals("Hello World World"); b = sb.equalsIgnoreCase("hello world world"); // returns true char c = sb.charAt(4); // returns 'o' b = sb.endsWith("World"); int index = sb.indexOf("World"); // returns 6 String aa = "one two one two"; int lastIndex = sb.lastIndexOf("one", 10); // searches backward from index 10 // index = sb.lastIndexOf("World", startIndex); // ***** String has length() method and Array has length attribute int length = sb.length(); // 17 b = sb.matches("^Hello.*"); // regular expression match returns true // ([{\^$|)?*+. regular expression metacharacters sb.replaceAll("^Hell.?", "Ola"); // ???? how does this work String[] sp = sb.split(" "); // split string based on regular expression String lowerCase = sb.toLowerCase(); String upperCase = sb.toUpperCase(); sb = sb.trim(); // trim whitespaces // convert int to string, also takes float, decimal etc String str = String.valueOf(5); sa = "abcdef"; sa = sa.replace('b', 'd'); sa = "abcdef"; sa = sa.substring(1); // begin -> "bcdef" sa = "abcdef"; // Note end not zero based sa = sa.substring(1, 3); // begin, end returns "bc" System.out.println("After substring sa=" + sa); // StringBuffer not immutable StringBuffer sbuf = new StringBuffer("hello"); sbuf.append(" ").append("world"); // can chain methods because of mutability sbuf.append(3); // append takes boolean, char, double, float, int long sbuf.insert(6,"to "); // offset, string -> "hello to world3" System.out.println("sbuf.insert=" + sbuf.toString()); sbuf = new StringBuffer("abc"); sbuf.reverse(); String s = "Hello,World"; java.util.StringTokenizer st = new java.util.StringTokenizer(s, ","); while (st.hasMoreTokens()) { String token = st.nextToken(); } } /** Math class is final Math class has all static methods 0.0 == -0.0 -1.0/0.0 == Infinity int Math.round(float) double Math.random() between >=0 and < 1 long Math.round(double) // only method to return int Math.floor() and Math.ceil() return type double All comparisons involving NaN and a non-Nan always result in false. Default type of a numeric literal with a decimal point is double. integer (and long ) operations / and % can throw ArithmeticException while float / and % will never, even in case of division by zero. double abs(double a) float abs(float a) int abs(int a) long abs(long a) double acos(double a) // Returns the arc cosine of an angle, in the range of -pi/2 through pi/2. double asin(double a) double atan(double a) double atan2(double y, double x) // Converts rectangular coordinates (x, y) to polar (r, theta). double ceil(double a) // Returns the smallest (closest to negative infinity) double value that is // not less than the argument and is equal to a mathematical integer. double cos(double a) // Returns the trigonometric cosine of an angle. * double exp(double a) Returns Euler's number e raised to the power of a double value. double floor(double a) // Returns the largest (closest to positive infinity) // double value that is not // greater than the argument and is equal to a mathematical integer. double IEEEremainder(double f1, double f2) // Computes the remainder operation on two arguments as // prescribed by the IEEE 754 standard. double log(double a) // Returns the natural logarithm (base e) of a double value. double max(double a, double b) takes float, long, int double min(double a, double b) takes float long int double pow(double a, double b) double random() // >= 0 and < 1 double rint(double a) // Returns the double value that is closest in value to // the argument and is equal to a mathematical integer. long round(double a) // Returns the closest long to the argument. int round(float a) // Returns the closest int to the argument. double sin(double a) // Returns the trigonometric sine of an angle. double sqrt(double a) // Returns the correctly rounded positive square root of a double value. double tan(double a) // Returns the trigonometric tangent of an angle. double toDegrees(double angrad) // Converts an angle measured in radians to an // approximately equivalent angle measured in degrees. double toRadians(double angdeg) // Converts an angle measured in degrees to an // approximately equivalent angle measured in radians. */ public static void math() { // double pi = Math.PI; double e = Math.E; float p_i = Float.POSITIVE_INFINITY; // e.g result of 16d / 0.0 float n_i = Float.NEGATIVE_INFINITY;// e.g result of 16d / -0.0 double notanum = Double.NaN; // 0.0d /0.0 if (notanum != notanum) {} // not equal if (Double.isNaN(notanum)) {} // true if (Double.isNaN(Math.sqrt(n_i))) {} // true if (Double.isNaN(Math.sqrt(-16d))) {} // true int x = Math.abs(-99); // 99 takes long, float, double x = Math.abs(-0); // 0 takes long, float, double // still returns Integer.MIN_VALUE as positive number does not fit // 0x80000000 = -2147483648 x = Math.abs(Integer.MIN_VALUE); System.out.println("abs(Integer.MIN_VALUE)=" + x); // ceil and floor take double only double d = Math.ceil(3.1); // returns double as 4.0 d = Math.ceil(-3.1); // returns double as -3.0 d = Math.floor(3.1); // returns double as 3.0 d = Math.floor(-3.1); // returns double as -4.0 // Math.round returns int or long long al = Math.round(1.6); // 2 adds 0.5 and does a truncate al = Math.round(-1.5); // -1 adds 0.5 and does a truncate al = Math.round(1.5); // 2 takes float and double al = Math.round(1.4); // 1 x = Math.max(1, -1); // can handle int, long, float, double x = Math.min(1, -1); // can handle int, long, float, double double r = Math.random(); // r >= 0.0 && r < 1 r = Math.sin(Math.toRadians(90.0)); // takes double as parameter r = Math.cos(Math.toRadians(90.0)); // takes double as parameter // cos() tan() r = Math.toDegrees(Math.PI * 2.0); // 360.0 takes double returns double // 6.283185 (Math.PI*2) takes double returns double r = Math.toRadians(360.9); r = Math.sqrt(9); // 3 takes double returns double } /** All primitive datatypes have wrapper objects for providing addtional functionality All wrapers immutable and final void, Void // can be instantiated char Character, int Integer extends Number long Long extends Number float Float extends Number double Double extends Number byte Byte extends Number short Short extends Number create using new or valueOf abstract class Number has byteValue(), shortValue() etc string to number can throw runtime NumberFormatException Character does not have any of the below // All Wrappers toString() static String toString(<primitive>) // convert to primitive static Wrapper valueOf(String s) static <primitive> parseXXX(String s) // only Integer and Long static String toHexString(int i) static String toBinaryString(int i) static String toOctalString(int i) static int/long decode(String s) can handle octal, hex etc static Integer/Long valueOf(String s, radix) static int Integer.parseInt(String s, int radix) // only Integer static Integer Integer.getInteger(String nm) // reads system property Long a = new Long(10); int b = new Integer(10); if (a.equals(b) {} // false */ public static void wrappers() { Character c = new Character('c'); // only one constructor Boolean bw = new Boolean(true); // takes bw = new Boolean("TrUe"); // case insensitive String true or false //if (bw) {} // won't compile Integer iw = Integer.decode("5"); // String to integer iw = Integer.valueOf("101"); iw = new Integer("42"); // valueOf and parseXXX take radix valueOf // returns Wrapper and parseXXX primitive iw = Integer.valueOf("101", 2); // in binary // can throw NumberFormatException (RuntimeException) int ai = Integer.parseInt("123"); Float fw = new Float("3.2f"); String s = Integer.toString(254, 16); // int to hex string s = Integer.toOctalString(254); // toXXXString Hex,Octal,Binary s = fw.toString(); // All wrappers implement toString() s = Float.toString(3.2f); ai = iw.intValue(); // xxxValue Wrapper conversion to primitive byte ab = iw.byteValue(); // equals checks if same type e.g iw = new Integer(42); // Short sw = new Short(42); // will not compile as 42 is int Short sw = new Short((short)42); if (iw.equals(sw)) {} // false // Immutable arbitrary-precision integers java.math.BigInteger bi = new java.math.BigInteger("123448273592"); java.math.BigDecimal bd = new java.math.BigDecimal("123.56728347"); } public static void wrapperArray() { Integer[] ss = new Integer[3]; Integer[] s2 = { new Integer(1), new Integer(2) }; Integer[] s3 = new Integer[] { new Integer(1), new Integer(2) }; Integer[][] a; a = new Integer[2][]; a[0] = new Integer[2]; a[0][0] = new Integer(1); } /** local variables have to be initialized before use int x; int k=1; if () x=1; else x=2; ++x; // OK if () x=1; if () x=2; ++x; // compiler error switch (k) { case 0: default: x =2; } ++x; //OK for (int i=0,j=0; i < 5; ++i) {} // OK int j=0; for (int i=0,j=0; i < 5; ++i) {} // Compiler error j declared twice */ public static void controls() { int i = 0; int j = 0; if (i == 0) { } else { } if (i == 0) { } else if (i == 1) { } else { } if (i == 0 && j == 0) { } // && is logical and || is logical if (!(i == 0)) { } // ! is negation if (i != 0) { } if (i != 0) ; else { } // if (i = 1) {} will not compile boolean b = false; // Not = insteadof == this will compile and run OK // requirement is that expression in () should evaluate to boolean if (b = true) { } // ternary operator short cut way of writing an if int r = (i == 0? i * 3: i * 5); // while (boolean expression) can't do while (int x = 0) {} while (i < 3) { ++i; } do { --i; } while (i > 0); do { System.out.println("do-while executed once"); } while (false); // i value never reaches 3 because of break // break must be in loop or switch else compile error r = 0; for (int k = 0,z = 0; k < 3; ++k,z++) { if (k == 2) break; // break out of loop ++r; } for (int k = 0; k < 1; System.out.println("for iteration")) { ++k; } // // Note continue must be in loop else compile error for (i = 0; i < 3; i += 2) { if (i == 2) continue; // skip ++r; } // we are naming these loops here outerloop: for (i = 0; i < 2; ++i) { innerloop: for (j = 0; j < 2 ; ++j) { if (i == 1 && j == 1) break outerloop; // breaks out of both for loops if (j == 0) continue outerloop; } } // will reach here on break outerloop // will run 3 times for (i = 0; i < 3 ; ++i) { here: if (i == 1) break here; } r = 0; final int x = 2; /** * switch takes int, short, byte, char * case has to have a final compile time constant * case cannot have duplicates * if switch has byte, case values should be less than 128 * else compile time error */ switch (r) { // if break not specified values will be 7 as code // is executed till break found case 0: r = 5; break; case 1: r = 7; //case 1: r = 20; break; // cannot repeat case default: --r; break; // default can be in the middle or top or end also case x: r = 9; break; case x + 7: r = 9; break; case 'a': r = 7; } byte by = 5; switch (by) { case 4: case 'A': break; } String s = null; // short circuited expression since s != null s.length() is not evaluated if (s != null && s.length() > 2) { // 'A' OK as it fits in byte // short circuited expression since s != null s.length() is not evaluated } } /** assertions disabled by default compile javac -source 1.4 foo.java runtime assert disabled by default Can also be programatically enabled or disabled using ClassLoader java -ea foo -da -disableassertions -ea -enableassertions -dsa -disablesystemassertions -esa java -ea -da:com.foo.bar blah disable assertion for com.foo.bar package and subpackages java -ea -da:com.foo... blah assert (true boolean expression) if false throw AssertionError can be any expression that returns value after : (not allowed void) Assert best practices use in private methods not in public OK to put assert postconditions at end of public method do not use in switch default expresion after : should not cause side effects sometimes OK to throw AssertionError explicitly AssertionError(all primitivet types) does not take String as constructor */ private static void assertCheck(int n) { assert (n >= 0) : "Negative number => " + n; assert (n <= 10); boolean b = n <= 5; assert b; assert b: n++; // bad causing side effect //assert (n <= 15) : foovoid(); will not compile as foo returns void } static void foovoid() {} // required for passing to inner class also in Thread // final can be added or removed for overridden methods // parameters to method are pass by value, so modification // inside method do not affect caller // Value of caller not changed only local copy changed public static void foo1(final int x) { } public static void foo2(int x) { x=5; } // caller will see the appended value public static void foo3(StringBuffer s) { s.append("s"); } int size = 7; // we are shadowing instance variable with local variable // note instance size will not be modified public static void foo4(int size) { size = 8; } // method return types static Object ret1() { int[] x = new int[1]; return x; } void ret2() { /* return "blah"; // compile error */ } class foo {} class bar extends foo {} foo ret3() { return new bar(); } // will compile OK // cannot make static -> class, constructor interface, inner classes, // inner class methods, local variables transient int x; // do not serialize volatile int y; // sync private copy in thread with master copy // Local variables -> final // Variables non local -> final public protected private static transient volatile // Methods final public protected private abstract // Concrete Methods synchronized strictfp native static public static void methods() { int x = 1; foo1(x); // x will remain 1 after call foo2(x); System.out.println(x); StringBuffer s1 = new StringBuffer("Hello"); foo3(s1); // contents of s1 can be modifed } /** new always allocates memory on the heap Java uses Garbage collection no need to do free Garbage Collecter varies by JVM implementation May use mark and sweep or reference counting Object is marked for garbage collection when no live thread has reference to the object Each Java app has one or more threads Note that until application exits main() thread is running finalize() may never be called finalize() method only called once finalize() exceptions ignored and garbage collection canceled */ public static void memory() { System.gc(); // hint to JVM to run garbage collector. May or maynot run // Ways to make object eligible for garbage collection String s1 = new String("s1"); s1 = null; // s1 now marked for garbage collection s1 = new String("s1"); String s2 = new String("s2"); s1 = s1; // s2 string eligible for garbage collection // we can also have islands of isolation where we have objects // refering to each other but no objects refering to them // at the end of method local variables eligible for garbage collection System.out.println( "TotalMemory (bytes)=" + Runtime.getRuntime().totalMemory() + ",FreeMemory=" + Runtime.getRuntime().freeMemory()); } public static void foo9(char c) {System.out.println("char");} public static void foo9(float f) {System.out.println("float");} public static void foo9(double d) {System.out.println("double");} public static void casting() { System.out.println("**** casting ****"); int i = 3; foo9(i); // calls foo9(float) } /** can handle primitives and Strings concatenated by + System.out.println("" + new Object()); // compilation error */ public static void print() { System.out.println("*** System.out.println ***"); // System.out.println only converts primitives //System.out.println("" + new Object()); // compilation error int i=0; float j=0; System.out.println(i + j); // prints 0.0 // will call Object.toString() System.out.println(new Object()); Object a = new String("A"); Object b = new java.util.ArrayList(); Object c = new java.util.Vector(); System.out.println("" + b + c); //System.out.println(b + c + ""); // compilation will fail } // We can name the args variables anything public static void main(String[] args) { primitives(); strings(); arrays(); wrappers(); math(); controls(); methods(); memory(); print(); casting(); assertCheck(-1); } }