oracle certified programmer
Second book, i will keep them apart in case i still want to take the exams. But probably an even shorter extract will be made that merges both book extracts.
Like the oca book extract i will use the same chapter divisions here.
recap
Overloading rules are regarded in this order :
- Exact match by type
- Matching a superclass type
- Converting to a large primitive type
- Converting to an autoboxed type
- Varargs
These overloading rules tend to go from exact to wider ...
Now mixing these could present some problems, because what order to keep in that case ?! But it usually complains about ambiguous calls so :
| ambiguous | |
|---|---|
Just don't overload like that, choose a better name if it's really needed
Overloading means the same signature...
- The access modifier must be the same or more accessible
- The return type must be more specific/restrictive also known as covariant.
- You cannot throw wider exceptions than the overridden method.
The methods may not be static, static methods are never overridden, they are hidden !!
Advanced Class Design
instanceof operator
It is a long one, but definitely an operator.
The operator a instanceof b returns true if A is an instance of class b, a subclass of b, or a class that implements b. Directly or indirectly.
This means for 'almost' all references a instanceof Object return true, except null because null is not an Object.
It is the internal object that's tested, not the reference type.
The format is : reference instanceof [Class|Interface], and it returns boolean
Note that comparing a dog and a cat, just like casting unrelated types does not even make it passed the compiler ! Note that this is only for classes, because a Cat just cannot be a Dog whatever happens. But for instance when we introduce an unrelated interface :
Mostly we use instanceof before a cast to test if it will work without ClassCastException.
virtual method invocation
This code explains it all :
This will print :
Java encounters an Animal reference, but underneath is a Dog data structure. It has a choice between Dog.call() and Animal.call(). I can only imagine that it works like this :
I think java uses a virtual method table in every object. Probably pointers to functions so not THAT big, and so it is easy call super.call() without having to traverse or lookup functions.
I would imagine in c this might look like this:
With this structure in mind. Most of the behavior can be explained except the ap->call();
- Reassigning from Dog pointer to Animal pointer makes it print "Animal name" instead of "Dog name".
- Reassigning from Animal pointer to Dog pointer makes a complete mess, so is not allowed.
- Invoking super get's us the members for the super class.
Only the method call will not work, but if you look something deeper you will see (with javap -v) that the call to call() and only() are done with the invokevirtual command :
Given this code :
Here is a javap -v dump of only the main method :
Actually, all calls are done with invokevirtual except the constructors (init).
From the java documentation this is what invokevirtual does :
Let C be the class of objectref. The actual method to be invoked is selected by the following lookup procedure:
- If C contains a declaration for an instance method m that overrides (ยง5.4.5) the resolved method, then m is the method to be invoked, and the lookup procedure terminates.
- Otherwise, if C has a superclass, this same lookup procedure is performed recursively using the direct superclass of C; the method to be invoked is the result of the recursive invocation of this lookup procedure.
- Otherwise, an AbstractMethodError is raised.
methods are found at runtime with a recursive algorithm, and variables are NOT.
toString()
The default toString() method from Object just prints the hashCode , but you can use the apache commons library to do it automatically :
| toString | |
|---|---|
ArrayList has an overridden toString() method, String[] uses the one from Object
equals()
Just using == compares the references to objects (identity), so you need to use .equals() to see if the contents are the same (equality)
If equivalence is used it means equality. Just say it out loud, a person is equal to another if it has the same qualities ( .equals() ), a person is identical to another is it IS that person ( == )
Stringbuilder has not overridden .equals() and i can still not find a good explanation since == already compares references and people expect .equals() to do a full compare. But still you should watch out for this :
| comparison | |
|---|---|
There are a number of rules (reflexive,symmetric,transitive,consistent) which are all automatically fulfilled in simple comparison. However you should always make sure x.equals(null) is false for x != null.
Always use @override on equals(). One easy oversight is that you should override boolean equals(Object) ... NOT boolean equals(YourObject) .
hashcode()
Simply the value used to put an object in some hashbucket when used in hash tables etc.
When you override equals() you are also expected to override hashCode() to match it. You will have to have a hashCode() function that puts two values that compare equal in the same bucket. (pt 2 below)
This means you will have to meet these criteria :
- Within the same program the result of hashCode() may not change.
- if equals() returns true on two objects, the result of hashCode() must be the same for both objects.
- The other way around is not needed, which means the hashCode does not have to be unique.
Point 3 is actually not a rule but a relaxation, so remember the first 2.
The hashcode is just an int (not long) , if you make one for an object with multiple members you can construct one from calling .hashCode on reference members (like String), rounding floats and add them together.
enums
Since enums are effectively a set of constants/finals use uppercase letters.
The semicolon at the end is not mandatory when you use only values, but when anything else is present they are needed. I opt for just always add it !
Behind the scenes enums are classes containing mainly static members. So helper methods are also allowed. Some are already defined like .name(), ordinal() or values() to loop over the values.
| enum | |
|---|---|
Every enum value has an ordinal() assigned but you can't compare int's with values like Weekday.SUN == 6. Ordinals can be used as index in arrays etc if needed.
Though ordinals behave a lot like classes they can NOT be extended.
switch
When used in a switch statement, it is actually NOT allowed to use the enum as prefix :
| switch | |
|---|---|
constructors
You could add more data to each member, which acts almost like a subclass of the enum.
| constructors | |
|---|---|
The member declarations must come before the rest, also all constructors are called when any of the enum members is used for the first time. So you get 7 calls at once in the Weekday case and after that no more.
The constructor is only allowed to be called from inside the enum and os therefore private !
You can also add a public abstract function to force all members to implement it.
nested classes
There are 4 flavours of nested classes, member, local, anonymous and static.
- Member inner class : defined at the level of members, cannot declare static fields or methods, can access all members of the outer class.
- Local inner class : defined inside a function, goes out of scope when the method ends. Has no access modifiers, cannot be static or use static members, can only access local variables if they are 'effectively final'.
- Anonymous inner classes, like local inner classes but without a name.
- Static inner class: defined at the static member level of a class, so no instance access.
member inner class
This is a normal class within a class, but to use it you need an instance of the outer class. This can be done in two ways :
- From within the methods of the "Outer" class.
- From outside of the outer class you use new as if it was a method of the outer class : new Outer().new Inner;
local inner class
This is local to a method, so it also goes out of scope at the end of the method.
Some rules for local classes :
- They do(can) not have an access specifier.
- They cannot be declared static or have static field or methods.
- They have access to all fields of the enclosing class.
- They have access to the local variables of the method if they are 'effectively' final.
That last one means they don't actually have to be declared final, like the localvar in the code above. localvar is effectively final in the second line, but not in the first line (++).
anonymous inner classes
Anonymous classes are also local but they have no name. But they need to either extend or implement so there is always something after new ....