Comments on Effective Java - 1 CompanionThis is the Wiki topic that is devoted to your comments on Effective Java - 1 Companion. All you need is a GFWiki user name and password. At the moment, it is (unfortunately) different from your java.net ID. Please comment based on the anchors in above document. Use null object design patternIf you return <code>null</code> from a method, consider to return a <it>null object</it>. <pre> If we used null object design pattern, the code could have been simplified as follows: <pre>
Unknown macro: { // all methods of SecurityManager will be empty public void checkRead(String name) { }
//... public class FileInputStream extends InputStream {
Unknown macro: { // security.checkRead(name); //}
security.checkRead(name); Do not rely on enum's ordinalsDo not use enum's ordinals e.g. for indexing in array. If you need to assign an integer to each enum constant, you can declare a field: <pre> public final int n; Makes(int n)
Unknown macro: { this.n = n; }
} Favor composition over inheritanceA recommended way to design the relationships between classes is to use relationships between objects described. For example, for classes <code>Computer</code> and The decorator design pattern should not be mentioned here (or at least not the way it is). The purpose of the decorator is to change the behaviour of another object (decoratee). And this is not the case here. Concerning the question whether to make classes final or not, it would depend on the project. For open source libraries and frameworks, I personally think that if we do not have very good reasons (e.g. security) to make a class final, it should not be final. If we do not want somebody to extend the class, we can write it to the documentation. But why to restrict users of our classes if we do not have to? For company projects, it could be reasonable to make classes final because we can keep colleagues from extending them. So, this supports the usage we want to. Forget about synchronized and use java.util.concurrentFor common tasks, such as producer-consumer, there are already classes in If you really need locking, use <code>Lock</code> and <code>ReentrantLock</code>. <pre> public void m() {
Unknown macro: { // ... method body }
finally
Unknown macro: { lock.unlock() }
} Lazy initializationLazy initialization is not very useful in Java because classes are loaded just before the first use. For example: <pre>
Unknown macro: { private static Singleton instance = new Singleton(); private Singleton() { }
public static Singleton getInstance()
Unknown macro: { return instance; }
... Class Singleton is fetched at the time of first call to Singleton.getInstance(), so the initialization of 'instance' is postponed till this time. One can also say that it is lazy initialization due to dynamic class loading. It has some limitations: e.g. if we had a class variable in Singleton, an access to this variable would have initialized 'instance'. Method overloadingI agree that method overloading should be used cautiously. However, I do not see any motivation for the rule "don't overload methods if they take same number of parameters". Should not the rule be rather "overload methods ONLY if they do the same job"? For example: <pre>
Unknown macro: { ... }
} km:
Unknown macro: { ... }
</pre> Zdenek: Concerning the sendMessage() above, if the messages sent by these two methods are of same type and differ only in content (for example, both of them are JMS TextMessage), I think overloading should be preferred here. A clue can be in this case: can a recipient of the message distinguish between messages sent by sendMessage() and sendConcatenatedMessage()? If not, it means that the methods do the same job (but with different data) and thus they should have the same name. Different names should be used only if they send different messages. For example, if sendMessage() sends TextMessage and sendConcatenatedMessage() sends ObjectMessage. One more argument to support my view to overloading: imagine that you know the sendMessage(List<String> content) method (you read the javadoc and used it several times). And now you want to send a message containing a single string. The context help will offer the sendMessage(String content) method. What will you do? I will expect that the method does the same as sendMessage(List<String> content) and probably call it without reading the javadoc. Now it seems to me that the right rule should be: We should use overload methods <i>if and only if</i> they do the same jobs. It is logical to use the same name for methods that produce the same result and it is misleading to use different names for the same actions. The only exception allowed from this rule is when overloading is not possible. For example, when two methods do the same and accept the arguments of same types: <pre>
Unknown macro: { ... }
} <i>Does anybody know when overloading appeared the first time in a programming language? <hr> From the sentence "All overloaded methods are implemented in a given class only." one could possibly think that you cannot overload a method from a superclass, which is not true: <pre>
Unknown macro: { System.out.println("int, double"); }
} class Child extends Parent {
Unknown macro: { System.out.println("double, int"); }
} BTW, would not be nice to have annotation @Overload here? km: Method overridingShould not be mentioned here that you can override only a method that is visible? Example: <pre> public class Parent
Unknown macro: { protected void m() { }
} import first.Parent; public class Child extends Parent // this is not overriding km: Zdenek: public class Parent
Unknown macro: { void m() { }
} import first.Parent; public class Child extends Parent // this is not overriding Immutable classesMaybe one could mention that even final fields can be modified by reflection: <pre> final class Final {
Unknown macro: { System.out.println(X); }
} public class Main {
Unknown macro: { Final p = new Final(); p.printX(); Field f = Final.class.getDeclaredField("X"); f.setAccessible(true); f.setInt(p, 42); p.printX(); }
} Item 3 of "Recipe for Writing Correct Immutable Classes": the memory model has already been reworked. Use exceptions properlyIn languages like C, where we do not have any exceptions, the code looks like as follows: <pre>
Unknown macro: { ... }
readFile(); closeFile();
Unknown macro: { ... }
</pre> A drawback of this approach is that we have to check if something bad happened after each call. The code of application is mixed with checking for errors in such case and we must be careful not to miss any checking. Exceptions remove this drawback and make the programmer's life easier if they are used properly. However, the proper use is not this: <pre> try {
Unknown macro: { ... }
try { </pre> One of the main advantages of exceptions, processing of errors in one place, is not used here. One should prefer the following style: <pre> SingletonsLet us answer the question "Should I implement the Singleton design pattern as a class with static methods or as a class with private constructor and static field?". Although the approach "class with static methods" is correct in some cases, it has a serious drawback. The drawback is that we lose many benefits of objects and late binding. For example, we cannot pass the singleton as a parameter to a method or exchange the implementation. <pre>
Unknown macro: { ... }
class MathImpl implements Math
Unknown macro: { private static final MathImpl instance = new MathImpl(); private MathImpl() { }
public static Math getInstance() ...
Unknown macro: { ... }
} Also, we can permit more implementations and let the user select one, e.g. by a system property: <pre>
Unknown macro: { String className = System.getProperty("mathimpl"); Class<?> clazz = Class.forName(className); Constructor<?> constructor = clazz.getDeclaredConstructor(); constructor.setAccessible(true); instance = (Math) constructor.newInstance(); }
catch (Exception e)
Unknown macro: { e.printStackTrace(); }
}
Unknown macro: { return instance; }
}
Unknown macro: { private MathImpl1() { }
//...
Unknown macro: { private MathImpl2() { }
//... In this case, we relieved the Singleton property because other subclasses of Math can be created. If this is not desirable, we can combine this approach with the Factory method pattern: <pre> // Math has package access
Unknown macro: { ... }
public class MathFactory {
Unknown macro: { return Math.getInstance(); }
} New StringsLet us investigate the question "Does it make sense to call the constructor <i>Zdenek: This is my answer to a similar question from the alias of Java instructors:</i> Let's have a look at the source code of String first: <pre>
Unknown macro: { /** The value is used for character storage. */ private final char value[]; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count; ... }
So, a string is represented by an array of chars. Let's continue with <pre>
Unknown macro: { throw new StringIndexOutOfBoundsException(beginIndex); }
Unknown macro: { throw new StringIndexOutOfBoundsException(endIndex); }
Unknown macro: { throw new StringIndexOutOfBoundsException(endIndex - beginIndex); }
Unknown macro: { this.value = value; this.offset = offset; this.count = count; }
So, when we call <code>substring()</code> on a string, a new string will share the <pre> There will be only one array of chars ('a', 'b', 'c', 'd', 'e', 'f'). Further, let's have a look at the constructor: <pre>
Unknown macro: { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. int off = original.offset; v = Arrays.copyOfRange(originalValue, off, off+size); }
else
Unknown macro: { // The array representing the String is the same // size as the String, so no point in making a copy. v = originalValue; }
The constructor distinguishes two cases:
|