300 likes | 417 Views
EECE 310: Software Engineering. Lecture 2: Understanding Objects in Java and Types. Why Java ?. Automated memory management Strong type safety for security Portability through VM No legacy baggage of C Excellent in-built libraries for networking/graphics. Brief history of Java ….
E N D
EECE 310: Software Engineering Lecture 2: Understanding Objects in Java and Types
Why Java ? • Automated memory management • Strong type safety for security • Portability through VM • No legacy baggage of C • Excellent in-built libraries for networking/graphics
Brief history of Java … • Developed by James Gosling at Sun in 1995 • Initially code-named ‘Oak’, was meant to target small, embedded devices (such as microwaves) • Became popular with the growth of WWW – Netscape had support for Applets • Mature alternative to C/C++ by late nineties • MS develops C# as alternative to Java (early 2000) • Today: Java used mainly in server/business apps
Learning Objectives • Differentiate between objects on stack and heap and understand garbage collection • Understand differences between mutable and immutable objects and Java calling semantics • Define apparent types and actual types and identify them for various statements • Identify implicit type conversions in Java and overloading
Objects and Variables • Local variables • Confined to single context: allocated on stack • Primitive types such as int or object references • Must be initialized before use (or fail compilation) • Objects • Shared among multiple procedure contexts • Allocated on heap using new operator • Can be initialized after creation (by constructor)
Variables and Objects: Example heap int i = 6; int j; int [] a = {1, 3, 5, 7, 9}; int [] b = new int[3]; String s = “abcdef”; String t = null; j = i; b = a; t = s; 1 3 5 7 9 i = 6 j j = 6 0 0 0 a b “abcdef” s t = null t Stack
Object references • All object references are uninitialized initially • Can be initialized to null, but not necessary • Need to explicitly allocate the object on the heap or assign it to (the start of ) an existing object • No pointer arithmetic possible once assigned • No need to explicitly de-allocate the reference (garbage collection frees it when not in use) • Can be passed to procedures and copied around
Example of Objects and References { Object b = null; { Object a = new Object(); b = a; } c = b.hashCode(); } Reference b is allocated on stack and initialized to null Reference a is allocated on stack Object is allocated on the heap and reference a points to it b and a both point to the same object a goes out of scope, so only b points to object b goes out of scope too, so nobody points to the object. Object is automatically reclaimed by garbage collector
Learning Objectives • Differentiate between objects on stack and heap and understand garbage collection • Understand differences between mutable and immutable objects and Java calling semantics • Define apparent types and actual types and identify them for various statements • Identify implicit type conversions in Java and overloading
Object Mutability • By default, Java objects are mutable • Modifications made through one reference will be visible when the object is accessed through another reference to the object • Example: Arrays • int [] a = {1, 3, 5, 7, 9}; • a[3] = -1; • b = a; • b[4] = -2; 1 3 5 7 9 1 3 5 -1 9 1 3 5 -1 -2
Exception: Immutable objects • State of immutable object never changes once it is assigned • Example: String object String s1 = “abcdef”; String s2 = “ghij”; String s3 = s1; s3 = s1 + s2; String s4 = s3; s4 = s2 + s1; “abcdef” “ghij” “abcdefghij” “ghijabcdef” Heap
Group Activity: Try it yourself What happens after these ? int[ ] a = {1, 2, 3}; int[ ] b = new int[2]; int[] c = a; intx = c[0]; b[0] = x; a[1] = 6; x = b[1]; inty = a[1]; What happens after these ? String s1 = “ace”; String s2 = “f”; String s3 = s1; String s4 = s3 + s2; s1 = s4; s4 = s1 + s2;
Java Calling Convention • Some textbooks will say the following • In Java, Objects are passed by reference, and primitives are passed by value… […] • This is wrong ! Java has only call-by-value • Both primitive types and object references are passed by value i.e., copied in to the stack frame • Can modify the object through the passed in reference provided object is not immutable
Calling convention: Call-by-value stack void foo(int a, int[] b) { a = a + 1; b[0] = 3; } heap a = 10 a = 11 b 0 3 0 0 int[] q = new int[3]; int p = 10; foo (p, q); // What are p and q’s value ? p = 10 q
Method calls in Java – Example 1 public static void swap(int a, int b) { int temp = a; a = b; b = temp; } m = 5; n = 10; swap(m, n); // What are the values of m and n here ? // (HINT: It’s not what you expect)
Method calls in Java – Example 2 public static void findAndRemove(int[ ] a, int m) { if (a ==null) return; // avoid null pointer exception for (int i = 0; i < a.length; ++i) { if (a[i]==m) a[i] = 0; } } int[ ] b = { 0, 2, 4, 6, 8 }; findAndRemove( b, 2 ); // What is the value of the array b here ?
Method calls in Java: Example 3 public static void padChars(StringBuffer s, int n) { for (int i = 0; i < n; i++) s.append(‘a’); } String str = “hello”; padChars(str, 5); // What is the value of str ?
Learning Objectives • Differentiate between objects on stack and heap and understand garbage collection • Understand differences between mutable and immutable objects and Java calling semantics • Define apparent types and actual types and identify them for various statements • Identify implicit type conversions in Java and overloading
Type Safety • Java is strongly typed (i.e., type-safe) • No “unsafe” casts are possible (e.g., reference to int) • Type-safety enforced by compiler (by language design) • Memory safety follows from type-safety • No writing past the end of an object (buffer overflows) • Automatic garbage collection provided by runtime, so no explicit frees or dangling pointers
Type Checking • Consider the following function: public static void findAndRemove(int[] a, int m); The compiler checks the call-site of the function to ensure that it matches its type-signature. int[] b = [0, 2, 4, 8, 10]; int n = 5; String s = “hello”; findAndRemove(b, n); // Is this legal ? findAndRemove(n, b); // What about this ? findAndRemove(s, n); // Ok, what about this ?
Type Hierarchy • Consider a type S which is a sub-type of T (say S is derived from T). Now, S can be substituted in place of T whenever a function expects T. • Example: All objects in Java are sub-types of Object, which defines an equals method. String s1 = “hello; Object 01 = s1; if ( 01.equals(“hello”) ) ….; // legal if ( O1.length() ) …. ; // illegal
Apparent vs. Actual type • Apparent type -- the type inferred from declarations • Actual type -- the type received at (object) creation • NOTE: Apparent type is a super-type of the actual type
Group Activity • Which of the following will compile ? For the ones that will compile, determine the result (or exception thrown) Object o = “abc”; Boolean b = new Boolean( o.equals(“a, b, c”) ); char c = o.charAt(1); Object o2 = b; String s = o; String t = (String) o; String u = (String) o2; char d = t.charAt(1);
Learning Objectives • Differentiate between objects on stack and heap and understand garbage collection • Understand differences between mutable and immutable objects and Java calling semantics • Define apparent types and actual types and identify them for various statements • Identify implicit type conversions in Java and overloading
Type Conversions • Type-checking is done using the apparent type of an object, NOT its actual type • If the actual type supports a member function, but the apparent type does not, it is ILLEGAL to invoke the member directly • However, if we cast the apparent type of an object to its actual type, we can invoke its member functions String s1 = “hello; Object O1 = s1; if ( ( (String)O1 ).length() ) …. ; // legal NOTE: If the actual type of the object does not match the cast type, a runtime exception is raised (ClassCastException) Example: (Integer)(O1) will raise a runtime exception
Type overloading • Same function can have multiple definitions based on argument types and/or return value • static int compare(int, float); // defn 1 • static int compare(float, float); // defn 2 • static int compare(float, int); // defn 3 • The compiler “knows” which definition to call depending on the type of the parameters • compare(5.0, 3); // Calls defn 3 • compare(5.0, 6.0); // Calls defn 2 • compare(3, 5.0); // Calls defn 1
Implicit Type Conversions • Often, the compiler will implicitly convert one primitive type to another (widening) • int => float • int => long • But long => int, float=>int NOT possible • So which version of compare do these call ? • compare(3, 5.0); // Definition 1 or Definition 2 ? • compare(5.0, 6); // Definition 2 or Definition 3 ?
Matching Rule for Implicit Conversions • “Most specific” method • Find the method that matches the types of the parameters with the least number of type conversions • Example: • compare(3, 5.0); // Calls definition 1 • compare(5.0, 3.0); // Calls definition 2 • compare(3, 4); // What about this one ? • NO “most specific method” compilation error • Can be avoided by explicit type-casting in the call such as compare(3, (float)4 );
Learning Objectives • Differentiate between objects on stack and heap and understand garbage collection • Understand differences between mutable and immutable objects and Java calling semantics • Define apparent types and actual types and identify them for various statements • Identify implicit type conversions in Java and overloading
Before the next class • Do exercises 2.1 to 2.7 in textbook for practice • Not graded, but will help in quiz preparation • Get acquainted with Java • Pick a partner by end of this week (or we’ll pick one) • Start working on Assignment 1 • Will involve basic Java programming • Due 3 weeks from today on your specific lab session