The Artima Developer Community
Sponsored Link

Java Buzz Forum
"Never accept null as a parameter and never return null."

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Adam Kruszewski

Posts: 90
Nickname: phantomik
Registered: Jan, 2005

Adam Kruszewski is (mostly) Java developer and linux system administrator.
"Never accept null as a parameter and never return null." Posted: Jan 26, 2005 6:47 PM
Reply to this message Reply

This post originated from an RSS feed registered with Java Buzz by Adam Kruszewski.
Original Post: "Never accept null as a parameter and never return null."
Feed Title: Adam Kruszewski :: WebLog();
Feed URL: http://adam.kruszewski.name/blojsom/blog/adam.kruszewski/?flavor=rss2
Feed Description: Thoughts about linux, open source, programming, ...
Latest Java Buzz Posts
Latest Java Buzz Posts by Adam Kruszewski
Latest Posts From Adam Kruszewski :: WebLog();

Advertisement
We all know this principle and we all know how hard is code defensively to keep it.
But it is a little easier now ;) Today AJDT team released developement version 2005012444759 of their Eclipse plugin, providing latest AspectJ5 capabilities to compile and wave J2SE 5.0 code with support to pointcuts matching annotated elements (there is no parameter and package annotations support right now).
Using annotations and one simple aspect we can check all calls to chosen methods and throw IllegalArgumentsExceptions whenever null value is passed to them. Here is how to do it:

  • First, create marker kind annotation (let's name it a "GoodCitizen") which we would use to mark methods which calls should be "null parameter" free.
    package sandbox.nullchecks;
    
    import java.lang.annotation.*;
    
    /**
     * Indicates methods which should behave as "Good Citizen".
     * In conjunction with GoodCitizenAspect all such methods
     * should throw IllegalArgumentException when there is 
     * null value passed to them or they return null value. 
     */
    @Retention(RetentionPolicy.CLASS)
    @Target( {ElementType.METHOD} )
    @Documented
    public @interface GoodCitizen {
    
    }
    
  • Then create aspect which will do the hard work:
    package sandbox.nullchecks;
    
    public aspect GoodCitizenAspect {
      
      // it will match any method call to annotated method with any signature.
      pointcut goodCitizenMethodCall() : call (@sandbox.nullchecks.GoodCitizen * *(..));
    
      before() : goodCitizenMethodCall() {
        Object[] methodArgs = thisJoinPoint.getArgs();
        for (int t = 0; t < methodArgs.length; t++) {
          if ( null == methodArgs[t] ) {
            throw (new IllegalArgumentException("Parameter " + (t + 1)
                + " of " + methodArgs.length + " in call to "
                + thisJoinPoint.getSignature()
                + " was NULL, but method is annotated as GoodCitizen."));
          }
        }
      }
    }
    
  • Now just try it! :)
    package sandbox.nullchecks;
    
    
    public class GoodCitizenExample1 {
    
      @GoodCitizen
      public void citizenTest(String str, int prim, Object obj) {
        System.out.println(str+":"+prim+":"+obj);
      }
      
      public static void main(String[] args) {
        GoodCitizenExample1 ex = new GoodCitizenExample1();
        // it should yell about null as third parameter when executed.
        ex.citizenTest("str", 9, null);
      }
    }
    
  • Running it produces this result:
    Exception in thread "main" java.lang.IllegalArgumentException:
     Parameter 3 of 3 in call to 
     void sandbox.nullchecks.GoodCitizenExample1.citizenTest(String,
     int, Object) was NULL, but method is annotated as GoodCitizen.
    
      at sandbox.nullchecks.aspects.GoodCitizenAspect.ajc$before
     $sandbox_nullchecks_aspects_GoodCitizenAspect$1$38402fab(GoodCitizenAspect.aj:23)
      at sandbox.nullchecks.GoodCitizenExample1.main(GoodCitizenExample1.java:13)
    

    Also note we could check method calls to all methods enclosed within annotated classes (link to sample source code is available on bottom of this post) but it requires runtime checks and it would be rather inefficient.

    As for "never return null" part I couldn't find a nice way of checking whenever method returned null or it's return type is void (after() returning(Object obj) advice threats void return type the same as when null is being returned). A little hackich way is to parse thisJointPoint.getSignature().toLongString() or create two annotations -- one for parameters checks and another one for return value checks and use them when apropriate.

    • 26-jan: update:
    Matthew Webster pointed me that I could define another pointcut like this:
      pointcut NonVoidGoodCitizenMethodCall() : goodCitizenMethodCall() && call(!void *(..));
    
    and then create after() returning advice which would catch all those non-void methods:
      after () returning(Object retValue) : NonVoidGoodCitizenMethodCall() {
        if (null == retValue) {
          throw (new IllegalArgumentException("Method "
            + thisJoinPoint.getSignature()
            + " returned NULL but it is marked as GoodCitizen."));
         }
      }
    

    Now it is a little easier to trace all those NullPointerExceptions out there. Happy hacking ;)

    As always compressed Eclipse project is available to download. Eclipse 3.1M4 and latest developement snapshot of AJDT are required.

Read: "Never accept null as a parameter and never return null."

Topic: The Architecture of Eclipse Previous Topic   Next Topic Topic: Free Wood Look and Feel beta

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use