Effective Java (2nd Edition)
by Joshua Bloch
ISBN 0321356683
Date Read 1/2011
My Rating
I read the 1st edition (my recommended book) a few years back. I just re-read the 2nd edition. It’s one of the best Java books around (the other must read would be Java Concurrency in Practice).
Read it.
Re-read it.
The 2nd edition is a little harder to read. Some chapters are too long and are not as cohesive (not like they were in the 1st ed), but still, getting all these tips from a Java champion is very valuable. At the very least, you can use his tips to win your arguments and influence others on your team.
And that’s the reason I’m recommending this book: read it to become a better Java programmer. Isn’t that a good reason?
|
Just as it is a good practice to make all fields private unless they need greater visibility, it is a good practice to make all fields final unless they need to be mutable.
–Brian Goetz
in Java Concurrency in Practice (page 48) |
Are you following these fundamental principles?
Just so we’re on the same page, an immutable object is on whose state cannot be changed after construction.
This view is supported by Joshua Bloch in Effective Java (2nd). Item 13 states: “Minimize the accessibility of classes and members.”
|
The single most important factor that distinguishes a well-designed module from a poorly designed one is the degree to which the module hides its internal data and other implementation details from other modules.
–Joshua Bloch
|
He goes on to say some fundamental principles.
|
A well designed module hides all of its implementation details, cleanly separating its API from its implementation. Modules then communicate only through their APIs and are oblivious to each others’ inner workings.
–Joshua Bloch
Effective Java (2nd), page 67 |
These are really the basics of information hiding or encapsulation. Basics of OOP programming! It’s a good idea to learn these well.
Think twice before making any fields public. Hold it. No, don’t make it public! Think twice before making it any other than private!
But to make sure you only expose what is absolutely needed requires some thought. You need your own judgment and experience.
As for the second part, item 15 states: “Minimize mutability.”
I think this one is a little harder to justify and not so obvious. But Bloch has some very good arguments. Together with Goetz, they convinced me that I should utilize immutability more often when I’m designing classes.
|
Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure.
–Joshua Bloch
|
Convinced!
But how? Follow these 5 steps (as per Bloch).
1. Don’t provide any methods that modify the object’s state.
2. Ensure the class can’t be extended.
3. Make all fields final.
4. Make all fields private.
5. Ensure exclusive access to any mutable components.
Goets says it a little bit differently.
An object is immutable if:
– Its state cannot be modified after construction;
– All its fields are final;
– It is properly constructed (the this reference does not escape during construction)
Immutable objects pack a lot of goodies in them.
One more time. Tell me what are the benefits of immutable objects!
They are simple to understand.
They are thread safe.
They require no synchronization.
Let’s end with a great summary note from Bloch, “Classes should be immutable unless there’s a very good reason to make t hem mutable.”
But.
If…
“If a class cannot be made immutable, limit its mutablity as much as possible.”
Strong statements.
Learn these design principles!
All in all, I recommend reading Item 15 from the Effective Java book. And re-read a few times until it becomes part of your design logic.
It’s all about getting better.
It’s all about improving.
It’s good to learn from the pros. Everybody needs a little guidance. I know I do. (These 2 books are excellent! Recommended.)
I am excited. For the first time, I can say that Java EE development can actually be fun and cutting edge. Jeremy Norris recently said, and I retweeted it, “If you’ve chosen Spring by default since 2005 for your EE needs, you owe it to yourself to take a real close look at JEE6.” I totally agree.
Just to give you some background. My exposure to Java EE has been limited. I have not really programmed in it. I did for 6 months or so, but it was in the J2EE 1.3 world and it was ugly/slow/overly complicated. I’ve tried to stay away from J2EE. Spring was a bit different. I’ve done Spring programming for a few years and generally have a good experience with it. But I don’t like too much XML configuration. I don’t like the fact you can easily get “tied” to the framework, which I don’t consider a best practice. Spring is a vast improvement over J2EE, but it’s not optimal either.
But now, Java EE 6 and Spring 3 enter a different ball game. I’m interested to see how it plays out. One thing I’m sure: the newest Java EE will be a good Spring competitor. Will it win? We’ll see.
I’ve always wanted the Java EE platform to be easier. JEE 5 went in that direction, but not far enough. Java EE 6 takes a few more steps. And I believe that it has crossed the “innovative/fun/cutting edge” line while allowing you to do some powerful stuff. Of course, it remains to be seen, but that’s what I feel now.
Here are some of the reasons why I think so…
No XML configs. Gone are EJB descriptors. Gone are JSF navigation rules. You don’t need XML for dependency injection. All of this means that this is really a big step forward. In some cases you might still need an XML config, but I like how it’s “configuration by exception” — that is, you might need one if you want to setup something other than the default configuration.
JSF 2 is fun. If you’ve ever developed web apps in Java, you know that it’s not optimal. I don’t like it when I see Java code inside JSPs. Who uses JSPs any more, anyway? Working with Spring MVC/JSTL is limited. Not bad, but tedious. But with JSF 2 and Managed Beans, you get a really nice, simple, and powerful solution. All you really need is one Managed Bean and one XHTML file. Really easy to get started. And I find this model of development intuitive: your view is tightly connected with the data. You don’t have to marshall/unmarshall the request in your controller. It’s done for you. Nice and simple!
JPA 2 is easy to use and robust. Powerful as well. It’s an excellent solution as an ORM. Ability to use JPA as a stand alone solution is also great.
EJB 3.1 is easy. Yes, easy. Want proof? Add @Stateless to your Java class and you’re done. No more configuration is needed. Want more? Create a webapp, add a Java class, and add a @Stateless bean. Deploy it to an app server and you have an EJB application! Done! No, you don’t need to package it to an EAR file (I hated that). Really cool.
Glassfish v3 is solid. It fully supports Java EE 6. I believe it’s the best EE application server out there. Good job to the team! Plus, with a stack of Java EE 6, Glassfish v3, and Netbeans 6.8 (no, it’s not my IDE), you can have a simple JEE app running in 5 minutes or so.
Testability. Embeddable containers. EJB has one. JPA has one as well. It’s really simple to setup some powerful integration testing. This is some serious stuff. You can test your database logic fully with an embedded database. EJB container testing is easy as well! Built in Java EE 6. You can test your EJBs with JUnit!
There are many other nice features with this release. I don’t know them all. And again, these are just my observations. So far, I’ve only read Beginning Java EE 6 with Glassfish 3 and tried a few things. Nothing serious. I’m going to learn more. I’m going to create applications based on it. This is some really exciting stuff. I just hope corporations that are still in the J2EE world move into the Java EE 6 world soon. They have good reasons for doing so now.
Java gets a lot of blame for not allowing straight multiple inheritance and for not implementing closures. But according to Bruce Eckel, you can do a multiple inheritance in Java, you can do closures – sort of. You can accomplish that with inner classes!
In this final Part 4 entry, I will concentrate on these two advanced topics.
One way that you can do multiple inheritance is just by implementing two or more interfaces. Easy and already possible in Java. But what if you did not have an interface, but rather abstract or concrete class. You can no longer just extend two of them — Java limitation. Inner classes provide different options.
First, let’s take a look at two different ways you can implement multiple interfaces.
// Two ways that a class can implement multiple interfaces. // Thinking in Java example interface A {} interface B {} class X implements A, B {} class Y implements A { B makeB() { // Anonymous inner class: return new B() {}; } } public class MultiInterfaces { static void takesA(A a) { } static void takesB(B b) { } public static void main(String[] args) { X x = new X(); Y y = new Y(); takesA(x); takesA(y); takesB(x); takesB(y.makeB()); } } // /:~
Note how class Y implements multiple interfaces. I admit that I have never used it like that. But it does implement two interfaces.
What if you had an abstract or concrete class. You can’t extend two classes easily. Not without the use of inner classes! Here’s how inner classes allow you to do that.
// With concrete or abstract classes, innerÄ… // classes are the only way to produce the effect // of "multiple implementation inheritance." // Thinking in Java example class D {} abstract class E {} class Z extends D { E makeE() { return new E() {}; } } public class MultiImplementation { static void takesD(D d) {} static void takesE(E e) {} public static void main(String[] args) { Z z = new Z(); takesD(z); takesE(z.makeE()); } } // /:~
Possible? Yes. Clean? Not really. But you can!
Eckel says that with inner classes you have these additional features:
1. The inner class can have multiple instances, each with its own state information that is independent of the information in the outer-class object.
2. In a single outer class you can have several inner classes, each of which implements the same interface or inherits from the same class in a different way.
3. The point of creation of the inner-class object is not tied to the creation of the outer-class object.
4. There is no potentially confusing “is-a” relationship with the inner class; it’s a separate entity.
What is a closure? “A closure is a callable object that retains information from the scope in which it was created,” says Eckel. If you’ve been reading this series, you know that an inner class maintains a link to the outer class — that’s in fact a closure.
The following example illustrates a closure. It’s long, but it’s worth getting comfortable with. (Plus, it’s the final example in the series!)
// Using inner classes for callbacks interface Incrementable { void increment(); } // Very simple to just implement the interface: class Callee1 implements Incrementable { private int i = 0; public void increment() { i++; System.out.println(i); } } class MyIncrement { public void increment() { System.out.println("Other operation"); } static void f(MyIncrement mi) { mi.increment(); } } // If your class must implement increment() in// some other way, you must use an inner class: class Callee2 extends MyIncrement { private int i = 0; public void increment() { super.increment(); i++; System.out.println(i); } private class Closure implements Incrementable { public void increment() { // Specify outer-class method, otherwise // you'd get an infinite recursion: Callee2.this.increment(); } Incrementable getCallbackReference() { return new Closure(); } } class Caller { private Incrementable callbackReference; Caller(Incrementable cbh) { callbackReference = cbh; } void go() { callbackReference.increment(); } } public class Callbacks { public static void main(String[] args) { Callee1 c1 = new Callee1(); Callee2 c2 = new Callee2(); MyIncrement.f(c2); Caller caller1 = new Caller(c1); Caller caller2 = new Caller(c2.getCallbackReference()); caller1.go(); caller1.go(); caller2.go(); caller2.go(); } } /* Output:Other operation11 2 Other operation 2 Other operation 3 *///:~ }
This has been a long series — a first for me. I have learned a great deal about inner classes. I hope you find these helpful as well.
Inner classes have their uses. They can help you implement an elegant solution. They can help you accomplish things not easily doable using alternative ways. They can also complicate your code a great deal. They can make your code unreadable. Use it with care.
Reference
Thinking in Java (4th), Bruce Eckel
Java Inner Classes – Part 1 – Intro
Java Inner Classes – Part 2 – Anonymous
Java Inner Classes – Part 3 – Nested Classes
In Part 1, I’ve covered the basics, in part 2, anonymous inner classes. Is there anything left about inner classes? Yes, there is. I warned you that inner classes are a beast.
In this part, I’ll cover nested classes.
When you create an inner class, there is a connection between the enclosed class and the inner class. Because of that, the inner class can access and manipulate the enclosed class.
Take that connection away and you have a nested class. A nested class is a static inner class. With a nested class, 1) you don’t need an outer class to create the instance and 2) you can’t access non-static outer-class object from the nested instance. Below is an example.
public class StaticInner { String s = "test"; public static class Inner { private int counter = 1; public int increment() { return counter++; } public void printS() { // StaticInner.this.s; // ERROR: No enclosing instance of the type StaticInner is // accessible in scope } } public static class Inner2 { private static int counter = 1; public static int increment() { return counter++; } } public static class Inner3 { public static class Inner3Inner { public void sayHi() { System.out.println("Hi"); } } } public static void main(String[] args) { System.out.println("Inner"); Inner inner = new Inner(); System.out.println(inner.increment()); // "1" System.out.println(inner.increment()); "2" Inner inner2 = new Inner(); System.out.println(inner2.increment()); // "1" // Inner2 has a static method System.out.println("Inner2"); System.out.println(Inner2.increment()); // "1" System.out.println(Inner2.increment()); // "2" // Inner3 has an inner class System.out.println("Inner3Inner"); Inner3Inner subInner = new Inner3Inner(); subInner.sayHi(); // "Hi" } }
In the main method, you can see that you can just instantiate Inner with new Inner(). Also in Inner, printS method tries to access StaticInner variable but it’s not allowed to. There is no connection between the two classes.
Initially, I thought a “static class” can have only one instance. That’s not true. Inner can have multiple instances, inner2 is a seperate instance and has its own object.
Inner2 is an example of a static instance. You can refer to in directly by Inner2.increment().
Inner2 shows that static inners can have more than one layer, Inner3Inner is defined inside Inner3.
Yes, you read that correctly. You can have an inner class within an interface! I did not know this was possible. Not that I would want to use it, but still… Take a look at the following example.
// Thinking in Java example public interface ClassInInterface { void howdy(); class Test implements ClassInInterface { public void howdy() { System.out.println("Howdy!"); } } } // Usage ClassInInterface test = new Test(); test.howdy(); /* Output: Howdy!*/// :~
It’s completely valid! Why would you want to do it that way? One valid reason is that if you wanted to have a common implementation of the interface. The downside is that the interface is “heavier” to carry around, but that’s probably very minor.
Back to the basic inner classes. Does a 2nd or 3rd level inner class have access to the layers above? Yes, it does, it has access to all layers. Thinking in Java has a great example, see below.
// Nested classes can access all members of all // levels of the classes they are nested within. class MNA { private void f() { } class A { private void g() { } public class B { void h() { g(); f(); } } } } public class MultiNestingAccess { public static void main(String[] args) { MNA mna = new MNA(); MNA.A mnaa = mna.new A(); MNA.A.B mnaab = mnaa.new B(); mnaab.h(); } } // /:~
I don’t like long tutorials nor long chapters. That’s why I’m breaking these into parts. When will it end? I have done 3 parts already and I’m not done! In Part 4, I’ll try to cover another advanced topic, Multiple Inheritance. Bruce Eckel has an interesting example.
Reference
Thinking in Java (4th), Bruce Eckel
Java Inner Classes – Part 1 – Intro
Java Inner Classes – Part 2 – Anonymous
In Part 1, Java Inner Classes – Intro, I covered most of the basics of inner classes. But there is much more. Some of it might get complex and confusing. But with all of that, I am beginning to understand and value what Bruce Eckel tries to say when he introduces inner classes.
At first, inner classes look like a simple code-hiding mechanism: You place classes inside other classes. You’ll learn, however, that the inner class does more than that–it knows about and can communicate with the surrounding class–and the kind of code you can write with inner classes is more elegant and clear, although there’s certainly no guarantee of this.
Initially, inner classes may seem odd, and it will take some time to become comfortable using them in your designs. The need for inner classes isn’t always obvious, but after the basic syntax and semantics of inner classes have been described, the section “Why inner classes?” should begin to make clear the benefits of inner classes.
In part 2, I am going to cover even more obscure, but more advanced topics. I like to learn by example, this part is heavy on examples.
Did you know you can define a class within a method? Yes, you can. It’s called a local inner class. Example below.
// Nesting a class within a method. // Example from Thinking in Java public class Parcel5 { public Destination destination(String s) { class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } } return new PDestination(s); } public static void main(String[] args) { Parcel5 p = new Parcel5(); Destination d = p.destination("Tasmania"); } } // /:~
How about a class within an “if” statement. Yes, you can do that as well. It’s called a class within arbitrary scope, see below.
// Nesting a class within a scope. // Thinking in Java example public class Parcel6 { private void internalTracking(boolean b) { if (b) { class TrackingSlip { private String id; TrackingSlip(String s) { id = s; } String getSlip() { return id; } } TrackingSlip ts = new TrackingSlip("slip"); String s = ts.getSlip(); } // Can't use it here! Out of scope: // ! TrackingSlip ts = new TrackingSlip("x"); } public void track() { internalTracking(true); } public static void main(String[] args) { Parcel6 p = new Parcel6(); p.track(); } } // /:~
One other interesting part about the example above is that the class TrackingSlip will get compiled and a class file created. However, this class will only be accessible from within the scope it got created in.
Did you know you can return a class from inside the method body? A class that is not accessible from anywhere else. A class that has no name. Yes, that’s why it’s called anonymous. See example below.
// Returning an instance of an anonymous inner class. // Thinking in Java example public class Parcel7 { public Contents contents() { return new Contents() { // Insert a class definition private int i = 11; public int value() { return i; } }; Semicolon required in this case } public static void main(String[] args) { Parcel7 p = new Parcel7(); Contents c = p.contents(); } } // /:~
Observe the syntax. The first statement in the method body is a return statement. It looks like you are returning a new instance of a class or interface. But that’s not it. You are actually creating/implementing the class, so you open a curly brackets { and close with }; and put the class definition inside. Very tricky and hard to get used to, I think.
Passing Arguments / Anonymous ConstructorWhat if you need to pass an argument and do some constructor initialization. It turns out you can.
// Creating a constructor for an anonymous inner class. // Thinking in Java example abstract class Base { public Base(int i) { print("Base constructor, i = " + i); } public abstract void f(); } public class AnonymousConstructor { public static Base getBase(int i) { return new Base(i) {{ print("Inside instance initializer"); } public void f() { print("In anonymous f()"); }}; } public static void main(String[] args) { Base base = getBase(47); base.f(); } } /** Output: Base constructor, i = 47 Inside instance initializer In anonymous f() */// :~
One note about arguments. If you’re using them inside the inner class, they have to be passed as final. In the above case, it’s not used directly so a non-final argument is fine.
More: You can even define an instance variable in an inner class!
Here’s a snippet from Thinking in Java that illustrates that:
public Destination destination(final String dest, final float price) { return new Destination() { private int cost; // Instance initialization for each object: {cost = Math.round(price); if(cost > 100) System.out.println("Over budget!"); } private String label = dest; public String readLabel() { return label; }}; }
Note that in the above example, because price was used in the inner class, it had to be defined as final.
Here’s a final note from Bruce about anonymous inner classes.
Anonymous inner classes are somewhat limited compared to regular inheritance, because they can either extend a class or implement an interface, but not both. And if you do implement an interface, you can only implement one.
More fun with inner classes to come! In Part 3, I’ll cover nested classes.
Reference
Thinking in Java (4th), Bruce Eckel
Java Inner Classes – Part 1 – Intro, The Pragmatic Craftsman
I believe in writing self-documented, easy to read code. I believe in mantra that simple is beautiful Inner classes are not good tools for that task. I think they make the task of writing good code much harder: weird syntax, different rules, etc. Mostly for that reason, I have not really learned inner classes. I rarely use them. But whether you like inner classes or not, they are a fundamental feature of Java. You can find examples of inner classes in the Java collections. Map.Entry is one example.
Where am I going with this? I think inner classes come useful in some circumstances. You can develop some really complex features with them. And as a Java developer, you should know what’s in your toolbox. Sooner or later you will come across them. You might have to read code that uses them. Or you might utilize them to make your task easier.
Either way, it’s time to learn inner classes.
My goal here is to create a series of articles/tutorials on inner classes with a goal of learning them on a more deeper level. I came across some very good references on inner classes in Thinking Java book by Bruce Eckel. I’ll mostly use that book, plus some other references for this series.
What’s an inner class? It’s a class defined within another class.
public class Outer { public class Inner { // inner fields, methods, etc } }
Simple, right? That’s basically where it ends. Inner classes have more privileges than regular classes. There are different types of inner classes. Like I said, it’s a beast.
One nice thing about inner classes is that they allow you to group related classes together. Comes in handy at times.
Take a look at the example above one more time. How would you create an instance of Inner?
Inner inner = new Inner(); // not going to work // how about -- seems like this should work Inner = new Outer.Inner(); // getting closer, but still not there // let's try to first create an instance of outer // and then use that to create an instance of inner Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();
Yes! That will work. But look at the syntax! Looks really weird to me. outer.new Inner() — but yes, that’s how you create an instance of inner.
One way to get around this weird syntax that Bruce Eckel uses is to create a method in outer that creates an instance of inner.
public class Outer { public class Inner { // inner fields, methods, etc } public Inner innerInstance() { return new Inner(); } } // now you can use Outer outer = new Outer(); Outer.Inner inner = outer.innerInstance();
I like that approach. Makes it much more readable.
So far, you’ve only seen how you would create an inner class. But what’s really different about an inner class?
Here’s a good example from Thinking in Java:
// Holds a sequence of Objects. interface Selector { boolean end(); Object current(); void next(); } public class Sequence { private Object[] items; private int next = 0; public Sequence(int size) { items = new Object[size]; } public void add(Object x) { if (next < items.length) items[next++] = x; } private class SequenceSelector implements Selector { private int i = 0; public boolean end() { return i == items.length; } public Object current() { return items[i]; } public void next() { if (i < items.length) i++; } } public Selector selector() { return new SequenceSelector(); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for (int i = 0; i < 10; i++) sequence.add(Integer.toString(i)); Selector selector = sequence.selector(); while (!selector.end()) { System.out.print(selector.current() + " "); selector.next(); } } } /** Output: 0 1 2 3 4 5 6 7 8 9*/
Note that SequenceSelector is a private class, and how end(), current(), and next() access fields in the enclosed class. Pretty neat, actually.
How would you access the outer object from within the inner? Guess what, another “tricky” syntax: Outer.this
public class SimpleOuter { private String name; private String getName() { return this.name; } private void setName(String name) { this.name = name; } public class Inner { public void accessOuter() { // note the SYNTAX SimpleOuter.this.setName("Test"); System.out.println("Outer name: " + SimpleOuter.this.getName()); } } public Inner inner() { return new Inner(); } public static void main(String[] args) { SimpleOuter outer = new SimpleOuter(); SimpleOuter.Inner inner = outer.inner(); inner.accessOuter(); } } /* Output:Outer name: Test*/
You can’t create an instance of an inner class without creating an outer instance first and using that instance to create the inner. Well, there is, if the inner is static (called nested class). More to come in Part 2…
I just read an overview of the Java EE 6 release. It looks like Java EE is becoming simpler, smaller, and less configuration hungry. Glad to that.
Few things that sound exciting to me: WebBeans, Profiles, JPA 2, JSF 2.
It’s probably a year or so away. I wish the process moved a bit faster.
Reference
Java EE 6 Overview
Related
On a related note, this article puts this direction into perspective, Towards Java EE Nirvana
I don’t think so, but it looks to me it’s going to be a good competitor in what it aims to do: dependency injection. I don’t know much about Guice, just heard about it couple of days ago, but the fact that it is coming from Google, it already has good following — at least in the blogoshpere.
Personally, I like it already. I hate writing the Spring’s XML files. I would much rather do it in Java. Guice claims to do that.
Spring is a good framework, no doubt about that. But you should not be too dependent on it. I know that’s not always the case, which is not good.
Drink some juice, I mean guice.
Java 6 is out. And it’s better than ever!
I do think it’s the best one ever. And the fastest ever. On one of my work projects, compiling Drools rule engine used to take over a minute, and with Java 6, this has been cut more than half. Nice improvement!
What are the exciting features in the new release?- Scripting support- Database enhancements (new DB embedded)- Web Services support
In this article, Mustang Must-Haves (link below), the author gives a short and sweet intro to some of the nice features from the new release.
I have to dig a little deeper into the release. One thing that comes to mind: Web services. Writing one in Java 6 is a piece of cake. However, I still find writing a web service client, a necessary component, not so easy. I know I can use a project such as Axis2 to generate the files for me, but I don’t think that’s the cleanest solution. I probably don’t know enough yet about the subject, but what’s needed is a great simplification in creating the web services client. There is no easy way. (I tried creating a client in NetBeans: it’s easy and it works, but behind the scenes it creates several classes, and besides, NetBeans is not really my IDE of choice.)
ReferenceMustang Must-Haves: What’s Cool in Java SE 6, devx.com article