Thinking in Java (Chapter 5)
===
###### tags: `Java` `OOP`
1. Many C bugs occur when the programmer forgets to initialize a variable
2. Cleanup is a special problem because it’s easy to forget about an element when you’re done with it the resources used by that element are retained and you can easily end up running out of resources (most notably, memory).
3. C++ introduced the concept of a constructor, a special method automatically called when an object is created.
4. Java also adopted the constructor, and in addition has a garbage collector that automatically releases memory resources when they’re no longer being used.
5. If a class has a constructor, Java automatically calls that constructor when an object is created, before users can even get their hands on it. So initialization is guaranteed.
6. The name of the constructor is **exactly** the same as the name of the class. The coding style of making the first letter of all methods lowercase does not apply to constructors
7. The constructor can also have arguments to allow you to specify how an object is created
8. A constructor that takes no arguments is called the default constructor
9. You don’t see an explicit call to some initialize( ) method that is conceptually separate from creation. In Java, creation and initialization are unified concepts—you can’t have one without the other.
10. The new expression does return a reference to the newly created object, but the constructor itself has no return value, and you don’t have an option
11. Method overloading
12. Most programming languages (C in particular) require you to have a unique identifier for each method (often called functions in those languages). Each function requires a unique name.
13. Method overloading allows you to use the same name
14. Each overloaded method must take a unique list of argument types. Even differences in the ordering of arguments are sufficient to distinguish two methods
15. If you don’t find an exact char match, it is promoted to int
16. If your argument is bigger than the argument expected by the overloaded method, then you must perform a narrowing conversion with a cast. If you don’t do this, the compiler will issue an error message.
17. You can also call a method and ignore the return value. This is often referred to as calling a method for its side effect
18. You cannot use return value types to distinguish overloaded methods
19. If you don't create constructor for a class Java will generate a default constructor for you
20. If you define any constructors (with or without arguments), the compiler will not synthesize one for you
21. The this keyword—which can be used only inside a non-static method—produces the reference to the object that the method has been called for
22. If you put this in when it’s not necessary, you will confuse and annoy everyone who reads your code
23. While you can call one constructor using this, you cannot call two. In addition, the constructor call must be the first thing you do, or you’ll get a compiler error message.
24. The compiler won’t let you call a constructor from inside any method other than a constructor.
25. Method static. It means that there is no this for that particular method. You cannot call non-static methods from inside static methods
26. You can call a static method for the class itself, without any object
27. It’s as if you’re creating the equivalent of a global method. However, global methods are not permitted in Java, and putting the static method inside a class allows it access to other static methods and to static fields.
28. Cleanup: finalization and garbage collection:The garbage collector only knows how to release memory allocated with new.
29. Java provides a method called finalize( ) that you can define for your class, to realise “special” memory
30. In C++, objects always get destroyed (in a bug-free program), whereas in Java, objects do not always get garbage collected
31. Garbage collection is not destruction.
32. If you pass a reference to an object into the static method (the static method could also create its own object). Then, via the reference (which is now effectively this), you can call non-static methods and access non-static fields.
33. If your program completes and the garbage collector never gets around to releasing the storage for any of your objects, that storage will be returned to the operating system en masse as the program exits.
34. Any activity that is associated with garbage collection, most notably your finalize( ) method, must also be only about memory and its deallocation
35. Finalize( ) is in place because of the possibility that you’ll do something Clike by allocating memory using a mechanism other than the normal one in Java. This can happen primarily through native methods, which are a way to call non-Java code from Java.
36. If the C++ object is created as a local (i.e., on the stack—not possible in Java), then the destruction happens at the closing curly brace of the scope in which the object was created.
37. If the object was created using new (like in Java), the destructor is called when the programmer calls the C++ operator delete (which doesn’t exist in Java). If the C++ programmer forgets to call delete, the destructor is never called, and you have a memory leak, plus the other parts of the object never get cleaned up. This kind of bug can be very difficult to track down
38. Java doesn’t allow you to create local objects—you must always use new. But in Java, there’s no “delete” for releasing the object, because the garbage collector releases the storage for you
39. System.gc( ) is used to force finalization
40. Garbage collector can have a significant impact on increasing the speed of object creation
41. Java heap is more like a conveyor belt that moves forward every time you allocate a new object, which is remarkably rapid
42. The “heap pointer” is simply moved forward into virgin territory, so it’s effectively the same as C++’s stack allocation
43. A page, memory page, or virtual page is a fixed-length contiguous block of virtual memory, described by a single entry in the page table.
44. Garbage collector collects the garbage it compacts all the objects in the heap so that you’ve effectively moved the “heap pointer” closer to the beginning of the conveyor belt and farther away from a page fault
45. Other languages: Each object contains a reference counter, and every time a reference is attached to that object, the reference count is increased. Every time a reference goes out of scope or is set to null, the reference count is decreased. Thus, managing reference counts is a small but constant overhead that happens throughout the lifetime of your program. The garbage collector moves through the entire list of objects, and when it finds one with a reference count of zero it releases that storage
46. Reference count: Objects circularly refer to each other they can have nonzero reference counts while still being garbage. Locating such self-referential groups requires significant extra work for the garbage collector, not used for any JVM
47. Trace reference of objects that is stored in stack or static storage so you could eventually find all the objects you are looking for. detached self-referential groups are automatically garbaged
48. Adaptive garbage-collection scheme: the JVM uses an adaptive garbage-collection scheme, and what it does with the live objects that it locates depends on the variant currently being used.
49. One of these variants is stop-and-copy. This means that—for reasons that will become apparent—the program is first stopped (this is not a background collection scheme). Then, each live object is copied from one heap to another, leaving behind all the garbage. In addition, as the objects are copied into the new heap, they are packed end-to-end, thus compacting the new heap, the reference to the object are automatically changed, other references points to the same object would also be found as the walk going on
50. Drawback of stop-and-copy: You have two heaps and you slosh all the memory back and forth between these two separate heaps, maintaining twice as much memory as you actually need. Some JVMs deal with this by allocating the heap in chunks as needed and simply copying from one chunk to another. A copy collector will still copy all the memory from one place to another while there's little or no garbage, which is wasteful, so it will switch to mark-and-sweep, which is faster when there's no garbage
51. With blocks, the garbage collection can typically copy objects to dead blocks as it collects. Each block has a generation count to keep track of whether it’s alive
52. Each block has a generation count to keep track of whether it’s alive. In the normal case, only the blocks created since the last garbage collection are compacted
53. JVM described here memory is allocated in big blocks. Each block has a generation count to keep track of whether it’s alive. In the normal case, only the blocks created since the last garbage collection are compacted
1. A JIT compiler partially or fully converts a program into native machine code so that it doesn’t need to be interpreted by the JVM and thus runs much faster.
1. When a class must be loaded (typically, the first time you want to create an object of that class), the .class file is located, and the bytecodes for that class are brought into memory
1. Drawbacks: JIT all the bytecodes: It takes a little more time, which, compounded throughout the life of the program, can add up; and it increases the size of the executable (bytecodes are significantly more compact than expanded JIT code), and this might cause paging, which definitely slows down a program
1. Lazy evaluation, which means that the code is not JIT compiled until necessary. Thus, code that never gets executed might never be JIT compiled
1. Member initialization: An uninitialized local variable is probably a programmer error, and a default value would have covered that up. Forcing the programmer to provide an initialization value is more likely to catch a bug.
1. Each primitive field of a class is guaranteed to get an initial value
1. the char value is a zero, which prints as a space
1. When you define an object reference inside a class without initializing it to a new object, that reference is given a special value of null
1. Specifying initialization: If you haven’t given object an initial value and you try to use it anyway, you’ll get a runtime error called an exception
1. Method can have arguments, but those arguments cannot be other class members that haven’t been initialized yet.
1. every object of type InitialValues will get these same initialization values.
2. Specifying initialization: If you haven’t given object an initial value and you try to use it anyway, you’ll get a runtime error called an exception
1. Method can have arguments, but those arguments cannot be other class members that haven’t been initialized yet.
2. You can’t apply the static keyword to local variables
1. Static object are initialized only when the first object which refers to them is created, after that it is not reinitialized
1. The order of initialization is statics first, if they haven’t already been initialized by a previous object creation, and then the non-static objects
1. To execute main( ) (a static method), the class must be loaded, and its static fields are then initialized, which causes those classes to be loaded, and if they contain static objects, Then it is loaded. Thus, all the classes in this particular program get loaded before main( ) starts. This is usually not the case, because in typical programs you won’t have everything linked together by statics.
1. Java interpreter must locate class, which it does by searching through the classpath.
1. When you create a new Dog( ), the construction process for a Dog object first allocates enough storage for a Dog object on the heap.
1. Setting all the primitives in that Dog object to their default values (zero for numbers and the equivalent for boolean and char) and the references to null.
1. Any initializations that occur at the point of field definition are executed when object created or trying to access static members
1. Java allows you to group other static initializations inside a special “static clause” (sometimes called a static block) in a class
2. The storage allocation (the equivalent of using new) is taken care of by the compiler in this case
3. anonymous inner classes
1. allows you to guarantee that certain operations occur regardless of which explicit constructor is called before constructors
1. int[] a1; exquals to int a1[];
1. int[] a1 = { 1, 2, 3, 4, 5 }; The storage allocation (the equivalent of using new) is taken care of by the compiler
1. it’s possible to assign one array to another in Java, so you can say: a2 = a1; What you’re really doing is copying a reference
2. If you go out of bounds, C and C++ quietly accept this and allow you to stomp all over your memory, which is the source of many infamous bugs. However, Java protects you against such problems by causing a runtime error (an exception) if you step out of bounds.
1. use new to create the elements in the array. Here, new works even though it’s creating an array of primitives (new won’t create a non-array primitive)
1. Arrays.toString( ) method is part of the standard java.util library, produces a printable version of a one-dimensional array.
2. C’s variable argument lists (known as “varargs” in C).
1. printArray(new Object[]{new A(), new A(), new A()}); print the class name and the address of the object.
1. The getClass( ) method is part of Object. The leading ‘[‘ indicates that this is an array of the type that follows. The ‘I’ is for a primitive int
1. enum creates a toString( ) so that you can easily display the name of an enum instance, which is how the print statement above produced its output.
1. The compiler also creates an ordinal( ) method for Enum to indicate the declaration order of a particular enum constant, and a static values( ) method that produces an array of values of the enum constants in the order that they were declared
1. enums can be used inside switch statements
1. enums are classes and have their own methods
1. Bjarne Stroustrup, the inventor of C++, was designing that language, one of the first observations he made about productivity in C was that improper initialization of variables causes a significant portion of programming problems
In cases where you don’t need destructor-like behavior, Java’s garbage collector greatly simplifies programming and adds much-needed safety in managing memory.
the garbage collector does add a runtime cost