The Source for Java Technology Collaboration
User: Password:



Felipe Leme's Blog

J2SE Archives


Final? Not yet...

Posted by felipeal on February 13, 2007 at 08:11 AM | Permalink | Comments (8)

Now that the pandora box is open is open, it is my turn to suggest a (possible worthless, I know) change to the Java language: the semifinal modifier!

I had this idea on my way home last week, after teaching the final keyword for my current Globalcode class. The idea was basically this: final is a well designed modifier, as it has a similar meaning on the many places it can be used (variable, method and class definitions). So wouldn't it be nice if there was a similar modifier for definitions that are not quite final?

Enters the semifinal modifier - too bad I didn't have this idea during the World Cup :-(.

The first and most useful case (if not the *only* useful case at all) is when defining a class: a class (or interface) marked as semifinal can be extended, but its public behavior cannot change. In other words, you can override any method of this class (as long as you do not make then more accessible than the original), but you cannot add any public method (or attribute).

The reasoning? I think such classes could be useful when defining APIs, frameworks, or components, where you do not want to allow extended classes to be more capable than its superclass (a side effect of this new class modifier is that the compiler could generate warnings when a subclass of a semifinal class is used as the type of a reference, parameter or method return). For instance, say you have an interface I that has methods mA() and mB(), and one implementation X that adds a method mC(). Over time, mC() becomes so popular and necessary that the clients of I always cast it to X, in order to call mC(). Well, if this method is so necessary, it should be part of I, and not an implementation detail - declaring I as semifinal would force it (i.e., X could not add a new public method mC()).
Here is an example:
semifinal class SuperClass {
   protected void m1() { 
   }
   protected void m2() { 
   }
   public void m3() {
   }
}

class SubClass extends SuperClass { 

   // declaration below is valid: same access level (protected)
   protected void m1() { 
   }

   // declaration below is not valid: more accessible (public)
   public void m2() { 
   }

   // declaration below is valid: overriding public method
   public void m3() { 
   }

   // declaration below is valid: new method, but private
   private void myMethod() { 
   }

   // declaration below is not valid: new public method
   public void myExtendedMethod() { 
   }
} 
To be honest, I never designed a long-lasting API, so I am not sure it makes sense at all - but if you make an analogy to Java EE specification and vendor-specific features, it might...

Now, if this new modifier is as orthogonal as final, it could be applied to variables and methods as well. In the case of a variable, it means its value must be defined at least once, and at most twice (and not exactly once, as it happens with final). I can see at least two situations where this is helpful:

1.When there is an optional assignment for an nonexistent value . Example:

semifinal MyObject o = getMyObject();
if ( o == null ) {
  o = new MyObject();
}
// from this point on, o is final and cannot be changed
Without semifinal, you have to either create a temporary reference:

final MyObject tmpObject = getMyObject(); // dirty hack
final MyObject o = tmpObject != null ? tmpObject : new MyObject();
Or not use final at all:

MyObject o = getMyObject();
if ( o == null ) {
  o = new MyObject();
}
// o can be changed, as it is not final
2.Before try/catch blocks:

semifinal MyObject o = null;
try {
   o = getMyObject(); // getMyObject() throws NastyException, which is checked
   // from this point on, o is final and cannot be changed
} catch( NastyException e ) {
  throw new NastyRuntimeException( "o is a nasty reference. No dessert for it!", e ); 
}
// we must use o from this point on, but it should not be changed
Again, without semifinal, we have to use the dirty hack or not use final at all:

MyObject tmpObject = null;
try {
   tmpObject = getMyObject(); // getMyObject() throws NastyException, which is checked
   // from this point on, o is final and cannot be changed
} catch( NastyException e ) {
  throw new NastyRuntimeException( "o is a nasty reference. No dessert for it!", e ); 
}
final MyObject o = tmpObject;
or

MyObject o = null;
try {
   o = getMyObject(); // getMyObject() throws NastyException, which is checked
   // from this point on, o is final and cannot be changed
} catch( NastyException e ) {
  throw new NastyRuntimeException( "o is a nasty reference. No desert for it!", e ); 
}
// we must use o from this point on, but it can be changed as it is not final

The final (no pun intended) case is the method definition: a semifinal method means it can be overriden, but at most by the direct subclass (i.e., it cannot be overriden more than once). To be honest, that's the less useful of the three situations (I mean, assuming the other two are any useful at all :-), but it would allow some interesting (not to say weird) possibilities, like this:

protected abstract semifinal void doIt();
Such definition means the method doIt() must be overridden by the subclass (as it is abstract), but is final after that (i.e., it cannot be overridden by a subclass of the subclass). It *might* be useful when implementing the Template Design Pattern, for instance.

Anyway, useful or not, that's just one idea I had in a 10-minutes car ride. I have no plans (neither time :-) to implement it, and it might not be as simple as it is described above - there are probably many corner cases to consider (like inner classes and generics), decisions to be made (for instance, it is clear that a subclass of a semifinal class must be defined as semifinal or final; but what about an overridden semifinal method?) and this is not just compiler fun (it might be in the case case of variables, but for methods and classes, that information must be somehow stored in the byteclass). But if someone has the nerves to give it a try, please let me know...

Who let the bugs out?

Posted by felipeal on November 22, 2006 at 05:00 AM | Permalink | Comments (4)

So, here is the deal. I've created a generic DAO class that looks like the following:

package net.felipeal;

import java.util.ArrayList;

public abstract class DAO<EntityInterface, EntityImpl extends EntityInterface> {
  
  private final Class<EntityImpl> entityClass;
  
  public DAO( final Class<EntityImpl> clazz ) {
    this.entityClass = clazz;
  }

  public List<EntityInterface> getEntities() {
    return getObjects(this.entityClass);
   }

  public <TInterface, TImpl extends TInterface> List<TInterface> getObjects(Class<TImpl> clazz) {
    return new ArrayList<TInterface>();
  }

}
The motivation behind this class is that the sub-classes will have the getEntities() method that would return all entities managed by the DAO, and still have the getObjects() method for other entities. So, for instance, I could have something like:

package net.felipeal;

import java.util.List;

public class ProductDAO extends DAO<Product, ProductImpl> {

  public ProductDAO {
    super(ProductImpl.class);
  }
  
  public static void main(String[] args) {
    final ProductDAO dao = new ProductDAO();
    final List<Product> products = dao.getEntities();
    final List<Customer> customers = dao.getObjects(CustomerImpl.class);
  }

}

The code above works on Eclipse 3.2, but when I try to compile it with javac 1.5.0_09, it fails:

[felipeal@localhost src]$ javac net/felipeal/DAO.java
net/felipeal/DAO.java:15: incompatible types
found   : java.util.List
required: java.util.List
    return getObjects(this.entityClass);
                     ^
1 error

So, looks like one of the two compilers is wrong: either javac should compile that code or (most likely) eclipse should have failed.

I tried a small variation that fails on Eclipse as well:

package net.felipeal;

import java.util.ArrayList;
import java.util.List;

public class DAO<EntityInterface, EntityImpl extends EntityInterface> {
  
  private final Class<EntityImpl> entityClass;
  
  public DAO( final Class<EntityImpl> clazz ) {
    this.entityClass = clazz;
  }

  public List<EntityInterface> getEntities() {
    final List<EntityInterface> list =  getObjects(this.entityClass);
    return list;
   }

  public <TInterface> List<TInterface> getObjects(Class<? extends TInterface> clazz) {
    return new ArrayList<TInterface>();
  }

}
In this class, Eclipse gives a similar error:

Type mismatch: cannot convert from List to List  bug-generics/src/net/felipeal DAOB.java line 15

That makes sense, as I'm using a wildcard and so there is no way to force the returned collection to be an interface implemented by the parameterized argument.

Any clue of what's wrong (with the code, not with the design itself, please :-)? As I'm not a generics expert, I'd like to hear some comments before opening an (possibly invalid) bug on BugParade or Eclipse...


Maven 1.0 released

Posted by felipeal on July 13, 2004 at 04:38 AM | Permalink | Comments (1)

I haven't blogged in a while - even after attending Java One 2004, which is source for blogging heaven - but I couldn't let this date pass on without making some noise.
From Maven's main page:

Maven 1.0 Released - 13 July 2004

Maven 1.0 has been released.
Download | Installation Instructions | Release Notes



'Nuff said..

Felipe

PS: and, of course, congratulations to the whole Maven team :-)


JDK 1.4.2_02 released

Posted by felipeal on October 22, 2003 at 06:31 AM | Permalink | Comments (1)

Yesterday was really a "release day". Not only JWSDP and JDeveloper had new releases, but also JDK 1.4.2.

Acording to the release notes, most of the changes are bug fixes. And even though these bugs don't affect the applications I'm using, I'm downloading it anyway (as I said earlier, it's time to move on :-).

It's time to move on

Posted by felipeal on October 05, 2003 at 08:16 PM | Permalink | Comments (11)

There's been a lot of talk lately about how Tiger (J2SE 1.5) is going to make Java easier to develop with, bringing it to the masses (or as Sun call it, to the "corporate developers"). I have no doubt that this promise *will* be fullfilled. My question is: *when* will that happen?

I'm not even talking about Tiger's release schedule here - although I'm also afraid it's is a little bit late already. My main concern is how long it will take for this release to be used by commercial products. Take as example J2SE 1.4: it's been available for years, and a lot of products - specially J2EE servers - still uses 1.3. I understand the fear of using a new major release right after it's available, but gee, we are talking about a very stable product, which recently reached it's 3rd version (1.4.2).

This "late adoption" trend is really bad: there is dozens of cool features available on 1.4 (like assert, logging and nio) that can't be used in many projects because they are bound on 1.3. That's not to mention the minor improvements, like new methods on existing classes that causes hard-to-debug NoSuchMethodException when you a deploy a class compiled with 1.4 in a 1.3 JVM. And now with Tiger and its language changes, this situation can be even worse, as the IDEs have to adapt themselves to these changes...

So, in order to reach the 10M developers mark, it's necessary a bigger effort than just providing new tools and APIs: it's necessary to move on!

Running ant in loop mode

Posted by felipeal on September 02, 2003 at 09:31 AM | Permalink | Comments (9)

Once in a while I work in a Java project where I need to run a simple Ant task many times in a short period of time. Like web projects where the JSP files are located in a directory under source control and are deployed in another directory by an Ant task. If I change a JSP file, I need to run Ant again, and it takes an eternity (about 5-6 seconds), due to the overhead of running the JVM, reading the XML files, etc...

Wouldn't it be nice if I could leave Ant running in a loop mode in those situations, so when I change the file I could redeploy it without that overhead?

For me, the answer is "Yes, that would be nice". But Ant doesn't have that feature, so now what? Now I can change Ant to include that feature, and that is the beauty of open source projects: if you want a new feature, you can just grab the code and implement it yourself. The same with bugs: rather than wait for the vendor to fix, test and publish a patch, you can open the code and nail the bug!

Now back to that new Ant feature: I created such patch and opened a bug for it.

We've been using it for a while in my team, and so far it's working fine. It's not in the basecode of Ant yet - and it might never be - so I upload the code to my site. If you liked the idea, please feel free to download it and give it a try. And if you like the results, give me some feedback through the bug's page or this weblog.



Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds