Zaawansowane programowanie obiektowe Lecture 1 Szymon Grabowski sgrabow@kis.p.lodz.pl http://szgrabowski.kis.p.lodz.pl/zpo11/ Łódź, 2011 Recommended literature / resources Bruce Eckel, Thinking in Java, Prentice Hall, 2006 (4th Ed.). http://download.oracle.com/javase/tutorial/index.html Cay S. Horstmann, Gary Cornell, Core Java 2 : Volume I – Fundamentals; Volume II – Advanced Features, Prentice Hall, 2007 (8th Edition). http://www.horstmann.com/corejava/corejava8.zip In Polish: Java. Podstawy. Wyd. VIII, 2008 (Helion), Java. Techniki zaawansowane. Wydanie VIII, 2009 (Helion). Paul Deitel, Harvey Deitel, Java for Programmers. Second Edition, Prentice Hall, 2011. Krzysztof Barteczko, Java od podstaw do techologii, tom 1 i 2, Mikom, 2004 (in Polish). In Polish: http://jacenty.kis.p.lodz.pl/systemy_multimedialne.html 2 A little bit of history Developed by Sun in 1995. Based on C++. Versions: 1.0.x, 1.1.x etc. up to SE 7 now (since July 2011). (Don't get confused: everything from v1.2+ is Java 2.) Java 2 in three editions: standard (SE), enterprise (EE) and micro (ME). For example, J2ME is for PDA’s (e.g. cell phones) – lighter. Android SDK: new platform, old (Java) language. 3 Design goals Portability (running on a Java Virtual Machine). High-level (objects, threads, exceptions, interfaces, packages, native zip handling...). Rich standard library (GUI, DB support, regexp, algorithms and data structures). Basically, there are three kinds of Java applications: • applets (interpreted and run by a web browser, on the client side); • servlets (on the server side); • stand-alone apps. 4 What makes Java safe Garbage collector. (No delete for objects, arrays... Objects no longer used will be deallocated automatically.) Exceptions everywhere. (In C++ they were optional. Here they are mandatory.) Applets – sandbox model. (Some operations not allowed, unless perhaps the applet’s digital signature is approved.) References, no (explicit) pointers. Strong typing. No implicit conversions (except some safe cases, see later), no int boolean conversion. 5 What makes Java slow See previous slide... But also, and this is the most important speed penalty factor, the thing that Java is interpreted by a JVM. 6 Java vs. C++, main differences (summary) Removed in Java: • preprocessor (#define, #include etc.) • operator overloading • (explicit) pointers • typedef • standalone functions; global variables • multiple inheritance • non-virtual methods. Added in Java: • interfaces • garbage collector • array bound checking, strong typing • concurrency support. 7 Create & run Java code [ http://ww2.cs.fsu.edu/~pfenning ] Five stages: 1. Edit – creating .java file 2. Compile – creating .class files (one .class file per built class). This is B-code (cmd-line: javac MyClass.java) 3. Load – loading bytecodes into memory 4. Verify – confirm bytecode validity and that it is secure 5. Execute – program execution (cmd-line: java MyClass – don’t type the extension) 8 Formatted output [ http://mcsp.wartburg.edu/zelle/python/ccsc-html/mgp00005.html ] No longer needed since J2SE 5.0 ! Use System.out.printf ("%10.2f", x); 9 Math ops – like in C (mostly) +, -, *, /, %, +=, /=, ++ (prefix and postfix) etc. ==, !=, <= etc. (returns true or false) int a = 10; // assignment Ternary op (like in C), example: System.out.println(height>=185 ? "Tall" : height>=170 ? "Medium" : "Short"); Examples: int x = 5, y = 7; int result = x++ * --y; // result? Don’t do it. Correct (if x, y small enough ints not to overflow!), but obscure code. int total = 5; int current = 4; total *= current + 3; // result? 10 Java-specific math operators && and || are like in C; they use short-circuit (aka lazy) evaluation, e.g. boolean cond = false; int x = 4; if (cond && x > 5) ... // cond – false the whole expression is false // i.e. (x>5) will not be evaluated But & and | for booleans mean almost the same, except for full evaluation. Beware: in C/C++ the operators & and | are AND/OR on the bitwise level! In Java, bitwise &, | and ^ (xor) still exist though. E.g. int n = 10 & 6 | 5; // n==7 11 Java-specific math operators, cont’d Other bitwise ops: ~ (negation), << (shift left), >> (shift right), <<=, >>=, >>>, >>>= (no equivalence in C/C++) >>> is unsigned shift right: regardless of the sign, zeroes are inserted at the higher-order bits. But the signed right shift >> uses sign extension: if the value is positive, 0s are inserted at the higher-order bits; if the value is negative, 1s are inserted at the higher-order bits. Example: int a = -11; PrintStream so = System.out; so.println(a >> 1); // -6 so.println(a >>> 1); // 2147483642 a = 11; so.println(a >> 1); // 5 so.println(a >>> 1); // 5 12 8 primitive data types char (single characters in Unicode, 2 bytes!, from '\u0000' to '\uffff') boolean (true or false; 1 byte) integer types (all signed): No unsigned byte (8 bits) types in Java! short (16 bits) int (32 bits) long (64 bits) floating point types: float (32 bits) double (64 bits) 13 Built-in data types, examples float x=3.5F, y=-5.92F, z; int n1 = 54; boolean trustworthy = false; char c = '\u1f00'; long theKeyToUniverse = 42353265264254219L; final double PI = 3.14; // keyword final means a constant! Printing variables: int x = 3; System.out.println("x is now " + x + ", isn't it?"); 14 Arrays, quick remainder (1 / 2) Indexes from 0. Same element type in a whole array. Stored in consecutive memory cells (hence O(1) access). Arrays may be passed to methods and returned from methods. Creating an array: int[] tab; // declare the array tab = new int[100]; // create the array tab[tab.length-1] = 5; // set the last item to 5 tab[tab.length] = 8; // IndexOutOfBoundsException! int[10] arr; // compile-time error! Create and initiate: int[] n = {10, 20, 30, 40}; // or: … = new int[]{10, 20, 30, 40}; 15 Arrays, quick remainder (2 / 2) Multi-dim arrays int[][] tab = new int[8][3]; // 8 rows, 3 columns int[][] c = { {5, 8}, {1, 2, 9}, {7, 4, 2} }; // What is c[1][2] ? // What is c.length ? 16 Arrays are objects! But of what class..? This is implicit (“hidden” to a programmer). E.g. the name of a 1-dim array of int’s is [I, the name of a 2-dim array of int’s is [[I, the name of a 1-dim array of double’s is [D etc. 17 Coping with array copying int[] a; int[] b = {5, 6, 7, 8, 9}; a = b; // WRONG ! Copied a reference, not the 5 elements of b Correct: a = new int[b.length]; for(int i=0; i < b.length; i++) a[i] = b[i]; There is a copy method in java.lang.System: arraycopy(sourceArr, src_pos, destArr, dest_pos, length); Example: System.arraycopy(b, 0, a, 0, b.length); Exceptions possible: NullPointerException (if sourceArray or destArray null), IndexOutOfBoundsException (e.g. src_pos negative), or ArrayStoreException (element type mismatch). 18 arraycopy demo [ http://java.sun.com/docs/books/tutorial/java/nutsandbolts/arrays.html ] Output: caffein int[] a = {1, 2, 3}; int[] b = a; b[0] = 10; // a[0] also changed, of course 19 Variable length argument lists (since SDK 5.0) Up to v1.4, this was a feature from C/C++ missing in Java. Same notation used (ellipsis). Argument list: type ... identifier. The type can be anything, even an array. Each method can only have a single type as a variable argument and it must come last in the parameter list. 20 Varargs, example (based on [W. Clay Richardson et al., Professional Java, JDK 5 Edition, Wrox, 2005]) 21 Previous example, can we have int sum(int[]) signature and still use e.g. sum(5, 10, -30)? Answer: no, the compiler reports an error. You can use sum(new int[] {5, 10, -30}) instead. Actually, the ellipsis is just syntactic sugar for having the compiler create and initialize an array of same-typed values and pass that array’s reference to a method. When the ellipsis can be used? E.g., for computing the average of a list (of e.g. floats), concatenating a list of strings into a single string, finding the max/min values in lists of floats. http://today.java.net/pub/a/today/2004/04/19/varargs.html 22 Varargs, example with arrays (based on [W. Clay Richardson et al., Professional Java, JDK 5 Edition, Wrox, 2005]) 23 Varargs, if at least one argument required (J.Bloch’s presentation, S48–49, http://files.meetup.com/1381525/still-effective.ppt.pdf) No args – fails at runtime. OK! No args – compile error. Other constructs (mostly) from C/C++ Loops: for(exp1; exp2; exp3) … for(T x: array_of_type_T) … // for-each while (expr) instr; do (inst) while (expr); Selection: switch (expr) { case var1: inst1; case var2: instr2; ... default: instr_def; } Java 7 25 Switch specifics The variable used in a switch statement can be an integer value of up to 32 bits, i.e.: byte, short, int, or char, or a wrapper class (Byte etc.) (*), or an enum (*). Or a string (since Java 7). (*) discussed later The value for a case must be the same data type as the variable in the switch, and it must be a constant or a literal. You cannot list more than one value after a single case. 26 Not quite C/C++ constructs break and continue made more flexible. int i = 0, j = 0; A reasonable outerloop: // label compromise between while (i < 100) stiff break / continue { in C/C++ i++; and most flexible but while (true) messy goto { (in many languages). j++; if (i + j > 10) break outerloop; // escapes to (*) } } // (*) 27 Data conversion What is b: double b = 1 / 3; // ? Just like in C/C++: integer division, result: 0. To obtain 0.3333333... use 1.0 / 3.0. And now, what is c? int c = 1.0 / 3.0; Compile error. Java wants to make sure you know you’d lose fractional information. Solution: int c = (int)(1.0 / 3.0); 28 Type conversions (arithmetic) int i; int2int short sh; sh = 5; // OK; 5 is int but is constant and // is small enough (no information loss) i = sh; // expanding, ok sh = (short)i; // OK – with the explicit cast double d = 5.12; float2int i = d; // WRONG! Conversion must be explicit // but: i = (int)d; // OK. The fraction is cut off 29 Integer arithmetic Java performs integer arithmetic at the int level, so e.g. b+c, where b and c are of type short, returns an int. The sum must therefore be cast to a short before an assignment to a, because a is a short: short a, b, c; c = 21; b = 9; a = (short) (b + c); // without casting – a compile error Similar example: byte a=4, b=-1; short c = (short)(a+b); 30 What’s wrong with that? float width = 5.5; // compile error Compiler message: possible loss of precision found: double required: float So, you should’ve written float width = (float)5.5; // explicit cast or (more naturally) float width = 5.5F; // or ...5.5f 31 Long division [ J. Bloch, N. Gafter, Java Puzzlers ] Output: 5 Correction: ... = 24L * ... (only in MICROS_PER_DAY is enough) 32 Methods (functions) Very much like in C/C++. Returned type declaration (possibly void), name, parameters... return keyword. Passing variables in Java always by value – a copy is made. No change of the variable in the called method affects its value when back in the caller. Aren’t some variables passed by reference though?? No. The reference’s (memory location’s) copy is passed to the second method. This works for objects (incl. arrays). 33 References Declaring an object is in fact only declaring a reference to it (no memory allocation for the object itself). This is different than with simple types (e.g. int)! Button b; // declaring a reference to a Button object b = new Button(); // now we create the object (Kind of) a special case: String objects. String s = "George Bush"; // !! What about String s = new String("George Bush"); // ?? It’s correct too, but it’s beating around the bush. 34 Little trap? String s1 = "abc"; String s2 = "ab"; s2 += "c"; boolean result = (s1 == s2); // true? False. Different objects (i.e., their references point to different memory locations). Content irrelevant. How to compare content then? if (s1.equals(s2)) ... or if (s1.equalsIgnoreCase(s2)) ... String s1 = "abc"; String s2; s2 = s1; // copy? No, just another reference. Write s2 = new String(s1); if a copy needed. 35 Concatenating strings and numbers String s1 = "Johnny has drunk "; int count1 = 2, count2 = 1; String s2 = " beers."; String s3 = s1 + count1 + s2; String s4 = s1 + (count1 + count2) + s2; String s5 = s1 + count1 + count2 + s2; String s6 = count1 + count2 + s2; What do s3, s4, s5, s6 store? Remember: evaluation from left to right. 36 Time for a little something [ http://www.javalobby.org/eps/more-puzzlers/ ] Answer: d. (Prints just “false”.) Because the + operator binds tighter than ==. 37 Obvious fix But wait. pig and dog are both final. Can’t we use the == operator then? With "Animals... " + (pig == dog) expression? No. That's because evaluation of dog needs invoking a method (length(), for the object pig, in our case) which must be done in the runtime. Hence, pig and dog are physically separate strings. But note: final String pig = "length: 10"; final String dog = "length: 10"; 38 // here pig == dog ! String literals are “interned” by the JVM s1 equals s2 ? true s1 == s2 ? false s2 == s3 ? true fs1 == fs2 ? true More on strings Lots of functionality in String class. See: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html A few examples: String c = "Abcde ".substring(2,4); if (c.startsWith("b")) System.err.println("What the hell?!"); c += " "; String d = c.trim(); // leading and trailing whitespace removed float f = 5.001f; String s = d.valueOf(f); // s.equals("5.001")==true now // valueOf is a static method from class String // object name here (d) irrelevant – String.valueOf(f) means the same c = c.toUpperCase(); // what if we write just: c.toUpperCase(); ? System.out.println(c.length()); 40 More on strings String s = "Abcde ".substring(2,8); /* Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 8 */ Maybe you meant String s = "Abcde ".substring(2, Math.min(8, "Abcde ".length())); String s = "abracadabra"; system.out.print(s.lastIndexOf("ab")); // 7 system.out.print(s.lastIndexOf("abb")); // -1, not found 41 String vs StringBuffer (1/3) Objects of class String are immutable in Java. String s = "test"; s[0] = 'b'; // compile-error: // array required, but java.lang.String found There is charAt(int i) method in String, but only to read. So, how can we e.g. append a character to a String?! Short answer: we cannot. We need to create another String: String s1 = "ice-cream"; s1 = s1 + "s"; // SLOW esp. if s1 is long // creates a temp object 42 String vs StringBuffer (2/3) [ http://java.sun.com/javase/6/docs/api/java/lang/StringBuffer.html ] Class StringBuffer – smth like String but its objects can be modified. At any point in time it contains some particular sequence of chars, but its length and content can be changed through certain method calls. StringBuffer sb = new StringBuffer(new String("start")); sb.append("le"); // "startle" or: sb.insert(4, "le"); // start starlet 43 String vs StringBuffer (3/3) [ http://java.sun.com/javase/6/docs/api/java/lang/StringBuffer.html ] [ http://mindprod.com/jgloss/immutable.html ] Every string buffer has a capacity. Initially (JDK 6) – 16 characters for an empty string buffer, and 16 + |str| if using public StringBuffer(String str) constructor. If the internal buffer overflows, it is automatically made larger. Why String immutable? • thread-safe. Two threads can both work on an immutable object at the same time without any possibility of conflict; • immutable objects are much better suited to be Hashtable/HashMap etc. keys. If you change the value of an object that is used as a hash table key without removing it and re-adding it, you lose the mapping. 44 Scanner class Breaks its input into tokens using a delimiter pattern (by default: whitespace). Convenient nextXxxx() methods for type conversion. Examples: Scanner sc1 = new Scanner(new File("myNumbers")); while (sc1.hasNextLong()) long aLong = sc1.nextLong(); 45 Scanner, various inputs are possible [ http://java.sun.com/j2se/1.5.0/docs/api/java/util/Scanner.html ] 46 Math class http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Math.html sin, cos, tan, atan, asin, ... exp, log (base e), ceil, floor, sqrt, ... min, max (lesser or greater of a pair), pow(a, b), random() (from [0,1)) static double toDegrees(double angrad), static double toRadians(double angdeg) rint(double a) – returns the double value that is closest in value to arg. a and is equal to a mathematical integer. Rounding to an even, in case of a “tie”. Constants: PI, E 47 javadoc (1) Writing documentation to large software projects: both very tedious and very important. javadoc is a simple tool to fascilitate it. Just comment each (public) function in the classes and run javadoc – the whole documentation will be generated (as a set of html pages). Sun Microsystem’s on-line documentation for the standard Java API was produced using javadoc. The documentation for each item must be placed in a comment that precedes the item. (This is how javadoc knows which item the comment is for.) 48 javadoc (2) Javadoc documentation in /** ... */. Special notation allowed: @return, @param. /** * Return the real number represented by the string s, * or return Double. NaN if s does not represent a legal * real number. * * @param s String to interpret as real number. From http://www.faqs.org/ * @return the real number represented by s. docs/javap/ */ advanced.html public static double stringToReal(String s) { try { return Double.parseDouble(s); } catch (NumberFormatException e) { return Double.NaN; } } 49 Classes Object-oriented programming is an exceptionally bad idea which could only have originated in California. / Edsger Dijkstra / Class is an object type. Basic syntax similar to C++. class WackyWindow { ... // data & methods WackyWindow(int x, int y) // constructor { ... } } // no ; as opposed to C++ In Java, method bodies are inside the class. 50 Constructor (example based on [Barteczko’00]) class Pair { int a, b; Pair(int x, int y) { a=x; b=y; } void add(Pair p) { a+=p.a; b+=p.b; } } class Pair { int a, b; Pair(int x) // single param. { a=x; b=x; } } 51 Default (=no-arg) constructor class X { int i, j; void setState(int a, int b) { i = a; j = b; } void showState() { ... } } ... X x = new X(); // OK (default constructor launched) But if we had class X { ... X(int a, int b) { ... } // "standard" constructor } then X x = new X(); // compile error 52 Keyword this (only in methods) Pair add(Pair p) { a = a + p.a; b = b + p.b; return this; } ... p.add(p1); p.add(p2); p.add(p3); But you can also type p.add(p1).add(p2).add(p3); // ! Why? this – reference to the current object 53 this in a constructor class Date { int year, month, day; public Date(int d, int m, int y) // one constructor { day = d; month = m; year = y; } public Date(int y) { this(1, 1, y); } // another public Date( ) // yet another constructor { this(2008); } } Based on an example from http://www.cs.fiu.edu/~weiss/cop3338_f00/lectures/Objects/objects.pdf 54 this specifics 55 Hiding identifiers Class fields can be hidden: class A { int a; void method(){ int a = 0; a = a + 10; this.a++; } ... // local var. // local var. // field of the object You can’t do it in blocks: int a; { int a; } // COMPILE ERROR This is wrong too: int i = 0; for (int i = 0; i < 10; i++) { ... } 56 Method overloading • int Fun(int x) • int Fun(float y) • int Fun(int a, float b) All they can appear in one class. But not • int Fun(int x) and • boolean Fun(int y) 57 Packages Packages are class libraries. To include (“import”) a package in your code, write smth like import java.util.*; Or you want to import a single class for a package? Example: import java.util.ArrayList; java.lang package is automatically imported. Using an imported class: either (in the same example) java.util.ArrayList or just ArrayList. More convenient than in C/C++: you can import a package more than once (no compiler complaint...), you can write the import... line in any place in your code. 58 Packages, cont’d Collisions possible: Say that you’ve created a class Vector in a package called school.my_cool_data_structures. But you’ve also imported java.util. Now, the line Vector v = new Vector(); makes a collision. Solution: use full path. java.util.Vector v = new java.util.Vector(); or school.my_cool_data_structures.Vector v = new school.my_cool_data_structures.Vector() 59 How to create an own package Very simply. Just write the code of your class (in a file with the same name as the class name) and start it with line e.g. package myutils.text; Your class will be added to the package myutils.text. Of course, there can be many classes in a package. Remember: earlier in the file than the package... line may be only comments. 60 Access modifiers (for classes, methods, fields) [ http://www.particle.kth.se/~lindsey/JavaCourse/Book/ Part1/Java/Chapter05/access.html ] Java provides 4 access modifiers: 1.public – access by any other class anywhere. 2.protected – accessible by the package classes and any subclasses that are in other packages. 3. default (also known as “package private”) – accessible to classes in the same package but not by classes in other packages, even if these are subclasses. 4.private – accessible only within the class. Even methods in subclasses in the same package do not have access. A Java file can have only one public class! 61 Access modifiers, visualized [ members.tripod.com/~psdin/comlang/basicJava.PDF ] no! If there is no direct access to a field (property), provide accessor / mutator (aka get / set) methods. 62 Why private (or protected)? To avoid accidental “spoiling” of some data. To provide a proper class interface (ensapsulation rule: hide unimportant details). C++ programmers, beware: put public / protected / private in front of EACH method or field you want to specify that way. (In C++, in contrast, an access specifier is valid for all the definitions following it until another access specifier occurs.) 63 Default package class X { // file X.java int x; void doSomething() { ... } } class Y { // file Y.java in the same directory void someMethod() { X x = new X(); x.doSomething(); // does it work? Can Y see components of X ? } } X’s components are NOT public. So the question is: are Y and X in the same package? We didn’t write package ... Yes! Because they are in the same directory and have no explicit package name. 64 Field initialization Fields are initialized to ZERO (0, false for the boolean type, null for references (i.e., object types)). BEWARE: local variables are not initialized (have random values)! Like in C/C++, by the way. But trying to read an unitialized variable yields a compile error. You can also explicitly initialize a field, e.g. class Pair { static String text = "Pairs"; static int x = -1; int a = x+1; ..... 65 Field initialization, cont’d We can also init object fields, e.g. class X { Flower f = new Flower(); ... } Or like that: class X { int i = f(); int j = g(i); ..... } But not ..... int j = g(i); int i = f(); // order matters! 66 More on cleanup Two ways: finalization and garbage collection. From Eckel’s TIJ, 3rd ed., chapter 4: Java provides a method called finalize() that you can define for your class. Here’s how it’s supposed to work. When the garbage collector is ready to release the storage used for your object, it will first call finalize(), and only on the next garbage-collection pass will it reclaim the object’s memory. So if you choose to use finalize(), it gives you the ability to perform some important cleanup at the time of garbage collection. But what for can we need finalize()? 67 Trap for C++ programmers GC or finalize() method are NOT equivalent to destroying an object (with the class destructor) in C++! The reason is, in C++ objects always get destroyed (and the programmer controls this moment) while in Java – not. (Perhaps an object will be destroyed, i.e. its storage will be garbage-collected (when? We don’t know), or perhaps not... – to save time.) 1. Your objects might not get garbage collected. 2. Garbage collection is not destruction. [ B.Eckel, Thinking in Java, 3rd ed., chapter 4 ] 68 So, what do we need finalize() for?? We may allocate space using native methods, i.e. calling non-Java code from Java. Example: allocate memory with C’s malloc(). Until free() called, storage will not be released. Of course, free() is a C and C++ function, so we need to call it in a native method inside our finalize(). But I won’t use that ugly C or C++ in my Java code! So, I will never need finalize(), right? Not quite true... 69 finalize(), interesting use [ B.Eckel, Thinking in Java ] Verification of the termination condition of an object. When we’re no longer interested in an object, it should be in a state whereby its memory can be safely released. E.g. the object is an open file, that file should be explicitly closed before the object is garbage collected. The value of finalize() is that it can be used to eventually discover this condition, even if it isn’t always called. If one of the finalizations happens to reveal the bug, then you discover the problem. 70 finalize(), interesting use, cont’d Code example (1/2) [ B.Eckel, Thinking in Java ] 71 finalize(), interesting use, cont’d Code example (2/2) [ B.Eckel, Thinking in Java ] 72 Static data, static methods static int n; // the field n belongs not to an individual object // but to the class // all class objects “see” the same value of n Static method – belongs to the class. It can access only static fields of the class. this not accessible. A static method cannot access non-static fields. Why? Since perhaps no object yet exists when we launch this method. (But a non-static method can invoke a static method, or access a static field.) 73 We already used API static methods System.out.println(Math.sqrt(2)); /* OK, although no Math object created */ Can we also do it like that? Math m = new Math(); System.out.println(m.sqrt(2)); No. The Math constructor is private. 74 String Tokenizer – useful class import java.util.*; ... String speech = "A lion, a witch..."; StringTokenizer st = new StringTokenizer(speech); while (st.hasMoreTokens()) { System.out.println(st.nextToken()); } Prints: A lion, a witch... Comments: 1-param constructor, hence default separators (spaces, CR, tabs). Wanna have .,: and space separators? Type ...new StringTokenizer(speech, ".,: "); Alternatives: Scanner, String.split. 75