pagetop
Javablog
by Java coders, for Java coders RSS

A few requests for Java 7, part 1

October 15th, 2007 by Sam

Java 7 is in development. I have a dream list of new language features including:-

  • operator overloading
  • subarray notation
  • terse equals notation
  • terse getter/setter notation
  • SuffixTree based regex

I have no idea how to bring these requests to the Java 7 team (some if not all of them, I’m sure they are fully aware of already)… but if anybody knows how I can pester them to consider these, please let me know! Add your own dream updates in the comments, or just feel free to criticise mine :-)

Operator Overloading

Oh please, please, please support a small set of symbols for operator overloading. This debate has been going on since Java began.

Imagine how clean code would be if mathematical sets could be manipulated by code such as

union = a + b;
intersection = a ^ b;
d = union - intersection;

Note these operators don’t affect the contents of a or b, but produce new objects. Operator overloading could also be used so that a + b adds b to a in the same way as a.addAll(b) works.

If the [index] notation could be overloaded, then imagine how much more terse your List code would be. This may cause some backwards compatibility problems with situations where people have used the + operator in a String concatenation context… but why not then allow overloading of only a few operators such as ++, --, and ** which are currently invalid syntax between Objects.

Subarray notation

Currently, the only way to get a sub-array is to use Arrays.subList (or roll your own). This is not only very verbose, but results in copies of primitive values. For mathematical code (especially when working with BLAS or LAPACK) this is disastrous for performance.

I suggest a notation for obtaining a reference to a subarray which indexes the same primitives and Objects as the parent array with no copying involved. A clean notation could be array[from : to]. This would be completely backwards compatible as the : symbol is currently not valid in this position.

Terse notation for a standardised equals

Comparing objects is somewhat awkward. See Effective Java for an excellent discussion on why this is so. The conclusion is that one must generate boilerplate similar to the following when the Object only has 2 internal state variables! (leftBank and torch):-

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    final ToyStoryState other = (ToyStoryState) obj;
    if (leftBank == null) {
        if (other.leftBank != null)
            return false;
    } else if (!leftBank.equals(other.leftBank))
        return false;
    if (torch == null) {
        if (other.torch != null)
            return false;
    } else if (!torch.equals(other.torch))
        return false;
    return true;
}

I envisage a shorthand notation such as

equals {
  getClass(), // or the keyword instanceof if it is preferred
  leftBank,
  torch
}

And if people want to create anything non-standard, then let them create the boilerplate. Given that code blocks cannot be named equals, this should be backwards compatible. (Disclaimer: don’t forget to override hashCode, which could also have a similar syntax). Dan has also suggested that annotations on fields may be a more Java alternative. Any update to the current ugliness would be great!

Getter/Setter variables shorthand

I recently learnt Ruby and it has a beautiful little shorthand for defining variables and their associated getter/setter methods. There is no reason why Java couldn’t adopt a similar thing… and imagine how much more terse it would make JavaBeans! For example, the following

private T blah;
/**
 * @returns blah
 */
public T getBlah(){
    return blah;
}
/**
 * @param blah
 */
public void setBlah(T blah){
    this.blah = blah;
}

could be summed up as

/** docs and annotations for blah go here */
getset T blah;

Indexing of String for fast repeated regex searching

This isn’t a language request, but for an additional class in the Pattern, Matcher suite.

I recently posted on the SUN Java forums requesting if anybody knew of an implementation of a Suffix Tree based regex engine. This alternative approach to matching regular expressions against Strings requires indexing the String (expensive), but leads to really fast searches.

Such an approach is appropriate to the case where a String is going to be searched many times. Consider the case of searching all the files in a folder. If the files don’t change but there are many searches performed… then it would make sense to create an index to improve search response time. If the indexes were Serializable it would allow for cross-session searching (instant Desktop-search backend!).

UPDATE: I’d also love to see boilerplate reduced for delegates… such as suggested by Blinkley


This entry was posted by by Sam on Monday, October 15th, 2007 at 8:56 pm, and is filed under Java, Java 7, equals, operator overloading, regex, subarrays. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.



16 comments on “A few requests for Java 7, part 1”

Hey guys, I’ve added this entry as a link on my Java 7 page.

wow, that’s a really great aggregation of ideas Alex!

As much as I think these ideas are good, but introducing new short-hand techniques typically increases complexity in that there’s then multiple ways of doing the same thing. Are you doing it to save you time or to reduce complexity? At what point does it cease to be programming and start to become somewhat scripting?

Operator overloading I think is a great idea, but again, one of Java’s aims was to simplify aspects whilst providing a high degree of control over code. Again, at what point does it defeat one of its purposes?

Great suggestions Sam! You’d get my vote if this were a democracy.

I’d love to see limited operator overloading. There are two common cases where it would improve the readability of code no end: accessing lists and maps.

The absurd thing is that Java already has the syntax array[i]. List.get(i) and List.set(i,value) are functionally equivalent to array access. So why can’t we use code like list[i]? What could go wrong? An added benefit is that it would abstract out the choice of arrays versus lists from a lot of code.

In maps, the [index] syntax would also be a big win for clarity. Consider and compare:

mymap.put(key, mymap.get(key)++);
mymap.put(a, mymap.get(b) + mymap.get(c));

versus

mymap[key]++;
mymap[a] = mymap[b] + mymap[c];

Which do you prefer?

These changes could be implemented for the List and Map interface without needing to invent a syntax for operator overloading. Better yet, create an interface IGetSetByIndex which List and Map can both extend. They would be purely cosmetic. The compiler would first transform [] syntax into get/set syntax. No change would be required in the JVM. The changes would be backwards compatible.

There is no downside! Please someone take note! This is a feature which pretty much every other language has.

Hi, getters and setters are really good features hope they will be included in the Java 7 (read about properties in Java 7). However from my point of view it is also very important to have import aliases, just like c++ or c#. This would be so great addition to Java - just imagine no more problems with naming classes - see awt and swing for a good example why import aliases are so needed (currently you have to avoid classes with same name, cause you will have problems to use them in the same time).


import java.awt.Component as AwtComponent;
import javax.swing.Component as SwingComponent;

So no more ClassName (like in swing) - total freedom of naming. That would be great. Hope, that someone will read this. Regards.

Marek… that would be great :-) I’m thinking specifically of OpenLAPI where some code is referencing up to 3 different classes of the same name (well, it did in this almost-release). Of course that is J2ME and would never get the benefits of Java 7 updates, but it just screams out at me how useful it would be.

Kezzer, I see your point… I must admit my biggest gripe about languages like Perl are that there are so many ways to do something that I just don’t know where to begin. However, that said… I really do feel that something must be done about the boilerplate in equals and limited operator overloading would be such a nice addition resulting in much more terse and readable code. It wouldn’t even be “a different way of doing it”, it’d just be a different way of writing it, which is very different as the logic and objects involved remain the same.

[…] The javablog had a post about several Java 7 requests: […]

Your equals construct is too specific IMO. See this blog pos. This allows you to write:

a .= b

and have it translated by the compiler to

(a == b || (a != null && a.equals(b)))

This is a solution that has much wider applicability, and would make a huge difference to readability.

Re. Sam’s suggestion for equals(), here is a static method which achieves some of what he wants.

/**
 * Compare two objects for equality.
 * @param a
 * @param b
 * @param testMe Strings specifying which properties to compare. These must
 * either be public fields or no-argument methods whose return values will
 * be compared (e.g. getters). Properties are tested using equals().
 * <p>
 * Note: We could extend to testing private fields and methods using setAccessible(true)...
 * @return true if equal according
 */
public static boolean equals(Object a, Object b, StringtestMe) {
    // Null tests
    if (a==null) return b==null;
    if (b==null) return a==null;
    // Should this be mandatory? It certainly risks subtle errors otherwise.
    // See Josh Bloch's Java puzzles for examples
    Class<?> clazz = a.getClass();
    if (clazz != b.getClass()) return false;
    // Test properties
    try {
        for (String prop : testMe) {
            Object af, bf;
            if (prop.endsWith("()")) {
                prop = prop.substring(0, prop.length()-2);
                Method f = clazz.getMethod(prop);
                af = f.invoke(a);
                bf = f.invoke(b);
            } else {
                Field field = clazz.getField(prop);
                af = field.get(a);
                bf = field.get(b);              
            }
            // Compare
            if (af==null) {
                if (bf != null) return false;
            } else if ( ! af.equals(bf)) return false;
        }
    // Convert class access exceptions into runtime exceptions
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    // All tests passed
    return true;
}

Stick that code in a utility class (e.g. MyUtitilities), and you can then access it like this:

public boolean equals(Object obj) {
    return MyUtitilities.equals(this, obj, "leftBank", "torch");
}

I think that’s pretty handy, but it isn’t as nice as a language feature. For a start it’s slower, and getting round the access restrictions would make it slower still. Also you still need to override hashcode.

And here’s an alternative based on adding an annotation

Example usage:

class MyObject {</p>
 
<p>@Equals
public String name;</p>
 
<p>private int id;</p>
 
<p>@Equals
public int getId() {
    return id;
}   </p>
 
<p>public boolean equals(Object obj) {
   return UtilityClass.equalsByAnnotation(this, obj);
}
public int hashCode() {
   return UtilityClass.hashcodeByAnnotation(this);
}</p>
 
<p>}
</pre></code></p>
 
<p>Here's the magic utility code which makes it work:</p>
 
<pre><code># lang java
/**
 * Indicates that this field or method should be used for equals() and hashcode().
 *
 * Warning: Only use with public fields and methods
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Equals {
}
 
     /** Test for equality based on properties annotated with equals()
     * @param a
     * @param b
     * @return true if equal by class and when all @Equals properties have been
     * tested using equals()
     */
    public static boolean equalsByAnnotation(Object a, Object b) {
        // Simple?
        if (a == b) return true;
        // Null tests
        if (a==null || b==null) return false;       
        // Should this be mandatory? It certainly risks subtle errors otherwise.
        // See Josh Bloch's Effective Java for examples
        Class<?> clazz = a.getClass();
        if (clazz != b.getClass()) return false;
        // Test properties
        try {
            Object af, bf;
            for (Field field : clazz.getFields()) {
                if ( ! field.isAnnotationPresent(Equals.class)) continue;
                af = field.get(a);
                bf = field.get(b);              
                // Compare
                if (af==null) {
                    if (bf != null) return false;
                } else if ( ! af.equals(bf)) return false;
            }
            for (Method f : clazz.getMethods()) {
                if ( ! f.isAnnotationPresent(Equals.class)) continue;               
                af = f.invoke(a);
                bf = f.invoke(b);               
                // Compare
                if (af==null) {
                    if (bf != null) return false;
                } else if ( ! af.equals(bf)) return false;
            }
        // Convert class access exceptions into runtime exceptions
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // All tests passed
        return true;
    }
 
    /**
     * Create a hashcode based on properties annotated with @Equals     
     * @param a
     * @return hashcode
     */
    public static int hashCodeByAnnotation(Object a) {
        final int prime = 31;
        int result = 1;
        Class clazz = a.getClass();
        // Test properties
        try {
            Object af, bf;
            for (Field field : clazz.getFields()) {
                if ( ! field.isAnnotationPresent(Equals.class)) continue;
                af = field.get(a);                              
                result = prime * result + (af==null? 0 : af.hashCode());
            }
            for (Method f : clazz.getMethods()) {
                if ( ! f.isAnnotationPresent(Equals.class)) continue;               
                af = f.invoke(a);               
                result = prime * result + (af==null? 0 : af.hashCode());                
            }
        // Convert class access exceptions into runtime exceptions
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }

It only works for public fields and methods. Also you have to beware of circular references creating infinite loops.

Stephen, I believe I’ve seen that before (in the form of a triple-equal === operator), and I’m totally in favour of in. Dealing with null really is what adds all that boilerplate! However, my concern with it would be that it would then leak out of equals methods and then we’ll have ==, .= and equals to worry about! Maybe that’s not such a bad thing, but in that case I’d probably like to @Deprecated Object.equals :-) (which is an insane modification)

Dan, actually… if helper classes are allowed, I’d probably prefer one that has the same semantics as the .= operator talked about above. That way, my code would look like

@Override
public boolean equals(Object obj) {
if (this == obj)
    return true;
if (obj == null || (getClass() != obj.getClass()))
    return false;
ToyStoryState other = (ToyStoryState) obj;
return (UtilityClass.equals(leftBank, other.leftBank)
       && UtilityClass.equals(torch, other.torch));
}

pretty much halving the boilerplate. I wonder if we could set up Eclipse to do it this way instead of doing everything explicitly?

The Annotation way looks very sweet! Would require some jiggery pokery to allow the JVM access to private fields, though.

I strongly agree with your zero-copy subarray feature, though I don’t particularly care how the syntax works.

I’d also like fast array compare methods, analagous to Arrays.equals(), based on C’s memcmp. Java’s Array.equals() or an equivalent array comparator are over an order of magnitude slower than C’s memcmp.

-Ian

@Ian fast array compare would be nice… somewhat related, were you aware that the CharSequence.compareTo is optimised by the Hotspot runtime for super-fast character comparisons. This is inherited by String.

Ashish Ranjan wrote:

In my opinion, the most urgently required thing in core language is HEREDOC feature. C#/Ruby/PHP/Perl every language has this feature and this is a must tool and also this feature can not be replicated by any java library, it should be part of java syntax itself. For example: Creating sql string with lots of string appends is a big headache, whereas it is boon to do the same with by heredoc(multiline strings) with/without interpolation.

bye :-) Ashish Ranjan ashishwave@yahoo.com

Leave a comment

Markdown is supported.

To include code snippets in your comment, use

<pre><code># lang java
... code here ...
</code></pre>

or use 4 spaces at the start of the line instead of using code and pre tags.

Comment feed: RSS