Crazy Ideas on import Statements

While not high on the list of “Things Java Could Do Better,” there’s plenty of ways we could reimagine the humble import. For most of us, the IDE handles our imports (thank you very much), so we don’t spend a whole lot of time thinking about them. Imports are a rather arcane way to make the compiler gods happy. I think they could look a little nicer, don’t you? Let’s look at your average set of import statements (taken from the Spring Framework, PortletWrappingController.java):

package com.implementsblog.post;

import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.EventPortlet;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.ResourceServingPortlet;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.NoHandlerFoundException;
import org.springframework.web.portlet.context.PortletConfigAware;
import org.springframework.web.portlet.context.PortletContextAware;
import org.springframework.web.portlet.util.PortletUtils;

First, what’s up with the package statement? It’s redundant since the file structure dictates the package (or is it the other way around?). (I’d really love the package keyword to be repurposed to mean “package-private access,” but that argument is for another post.) Next, why so many imports? Why not let import take an array or something similar?

import {
    java.util.Collections,
    java.util.Enumeration,
    java.util.HashSet,
    java.util.LinkedHashMap,
    java.util.Locale,
    java.util.Map,
    java.util.ResourceBundle,
    javax.portlet.ActionRequest,
    javax.portlet.ActionResponse,
    javax.portlet.EventPortlet,
    javax.portlet.EventRequest,
    javax.portlet.EventResponse,
    javax.portlet.Portlet,
    javax.portlet.PortletConfig,
    javax.portlet.PortletContext,
    javax.portlet.PortletSession,
    javax.portlet.RenderRequest,
    javax.portlet.RenderResponse,
    javax.portlet.ResourceRequest,
    javax.portlet.ResourceResponse,
    javax.portlet.ResourceServingPortlet,
    javax.xml.XMLConstants,
    javax.xml.namespace.QName,
    org.springframework.beans.factory.BeanNameAware,
    org.springframework.beans.factory.DisposableBean,
    org.springframework.beans.factory.InitializingBean,
    org.springframework.web.portlet.ModelAndView,
    org.springframework.web.portlet.NoHandlerFoundException,
    org.springframework.web.portlet.context.PortletConfigAware,
    org.springframework.web.portlet.context.PortletContextAware,
    org.springframework.web.portlet.util.PortletUtils
}

That looks better. Let’s take this idea to the extreme and nest them like a directory tree:

import {
    java.util {
        Collections,
        Enumeration,
        HashSet,
        LinkedHashMap,
        Locale,
        Map,
        ResourceBundle
    },
    javax {
        portlet {
            ActionRequest,
            ActionResponse,
            EventPortlet,
            EventRequest,
            EventResponse,
            Portlet,
            PortletConfig,
            PortletContext,
            PortletSession,
            RenderRequest,
            RenderResponse,
            ResourceRequest,
            ResourceResponse,
            ResourceServingPortlet
        },
        xml {
            XMLConstants,
            namespace.QName
        }
    },
    org.springframework {
        beans.factory {
            BeanNameAware,
            DisposableBean,
            InitializingBean
        }
        web.portlet {
            context {
                PortletConfigAware,
                PortletContextAware
            },
            ModelAndView,
            NoHandlerFoundException,
            util.PortletUtils
        }
    }
}

Part of me says this is more elegant, but part of me says it’s too hard to read. Our IDEs could help us by highlighting the path of the selected import; something like this:

org.springframework {
        beans.factory {
            BeanNameAware,
            DisposableBean,
            InitializingBean
        }
        web.portlet {
            context {
                PortletConfigAware,
                PortletContextAware
            },
            ModelAndView, <--Cursor is here
            NoHandlerFoundException,
            util.PortletUtils
        }
    }

Nah, that’s too weird, lets go back to one import per line. Since imports are only for the compiler, what if we didn’t have to state an import unless it was ambiguous? If I have a class named ReallyUniqueClassName you’re telling me the compiler can’t figure out the fully qualified name for me? I don’t buy it. But if I use List, it could be either java.util.List or java.awt.List, and I should be able to put import util.List at the top of my file. Listing each and every import makes sense if you’re not using and IDE, but you are using and IDE, aren’t you?

One final thought: isn’t it weird that packages don’t nest? For example, the package cool has no relation whatsoever to cool.beans. Even the Java Spec uses the word “subpackage” all over the place, but technically a package and its subpackage have no special treatmeant, they’re just like any two packages. This is despite the fact that

  1. Package names must match folders
  2. the folder beans/ is nested inside cool/

How would we structure our code if cool.beans was in the package cool? For starters, we could achieve a kind of “module privacy” by putting package-private classes in the root package of our project (somewhere like com.company.project). We wouldn’t be able to seal our packages, but is that such a bad thing? (You can still seal JARs, at least.)

But what do I care, I let the IDE do my importing for me, right?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s