The problem with the reconnect method is that it is easy to use but very hard to use correctly. In general, we try to avoid giving programmers methods that make it easy to hang themselves. We provide plenty of rope, and they are free to make a noose; we just don't provide a tieTheKnot method.
The basic problem has to do with clean up that happens when a session dies. Obviously ephemeral nodes will go away. Our watch reestablishment patches could be updated to make watches reestablish on reconnect, but that would be very confusing to have ephemerals disappear but watches get reestablished.
To ZooKeeper an expired session is a dead client, so by making the ZooKeeper service handle die as well we have clear semantics.
As an historical note, session expiration wasn't always a fatal thing. We used to delivered the session expiration event and then get a new session. The earliest problem our users ran into was with multi-threaded applications. If there are multiple threads going, the watcher object will get the session expired event; the other threads may still be trying to use the ZooKeeper object. If you use the same ZooKeeper object to reconnect with, you can easily end up with a thread that uses the object thinking that it is running in the context of an earlier session and really mess things up. The explicit reconnect alleviates this slightly, but you would still need to do synchronization around the ZooKeeper object and it would be very difficult to get working when you are using different libraries using the same ZooKeeper object.
You are working on a lock class; you can imagine someone else does a barrier class. Who is in charge of doing the reconnect() and deciding when it is safe?
Testing applications that use this would also be a pain given the number of race conditions involved.
So the safest thing to do is have the lock object become invalid when it's ZooKeeper object becomes invalid. An expired session is a really bad thing, we can't hide it nicely.