10

Is there any shorthand way of defining and using generic definitions without having to keep repeating a particular generic description such that if there is a change I don't have to change all definitions/usages though out the codebase for example is something like this possible:

Typedef myGenDef = < Object1, Object2 >;

HashMap< myGenDef > hm = new HashMap< myGenDef >();

for (Entry< myGenDef > ent : hm..entrySet())
{
.
.
.
}

5 Answers 5

12

There's the pseudo-typedef antipattern...

class StringList extends ArrayList<String> { }

Good stuff, drink up! ;-)

As the article notes, this technique has some serious issues, primarily that this "typedef" is actually a separate class and thus cannot be used interchangeably with either the type it extends or other similarly defined types.

Sign up to request clarification or add additional context in comments.

3 Comments

It may not be a good idea to accept an antipattern as a solution to your question, especially when there are alternatives. But if it helped you out with your particular problem...
(Disregarding the moderators' admonition on noise on the "typedef in Java" threads)... That's worse than an anti-pattern. It creates a new first-class type, with its own entries in the virtual method tables, and all such obligations. A C++ typedef would merely make the "ArrayList<String>" part DRY, so you can change String (or ArrayList) in only one place.
Yes, C/C++ typedefs are a well-respected language feature with good support and plenty of legitimate uses. This is not. Hence the whole "antipattern" thing.
4

In a generic method, you can use a limited form of type inferrence to avoid some repetitions.

Example: if you have the function

    <K, V> Map<K, V> getSomething() {
        //...
    }

you can use:

final Map<String, Object> something = getsomething();

instead of:

final Map<String, Object> something = this.<String, Object>getsomething();

Comments

3

Use Factory Pattern for creation of Generics:

Method Sample:

public Map<String, Integer> createGenMap(){
        return new HashMap<String,Integer>();

    }

Comments

2

The pseudo-typedef antipattern mentioned by Shog9 would work - though it's not recommended to use an ANTIPATTERN - but it does not address your intentions. The goal of pseudo-typedef is to reduce clutter in declaration and improve readability.

What you want is to be able to replace a group of generics declarations by one single trade. I think you have to stop and think: "in witch ways is it valuable?". I mean, I can't think of a scenario where you would need this. Imagine class A:

class A {
     private Map<String, Integer> values = new HashMap<String, Integer>();
}

Imagine now that I want to change the 'values' field to a Map. Why would exist many other fields scattered through the code that needs the same change? As for the operations that uses 'values' a simple refactoring would be enough.

Comments

1

No. Though, groovy, a JVM language, is dynamically typed and would let you write:

def map = new HashMap<complicated generic expression>();

1 Comment

Same with Scala. These languages offer syntax which can infer types from variable instantiation statements. This is similar to what is offered in .NET with the var keyword. Don't confuse this with weakly (or loosely) typed languages which let you chance a variable type on the fly; the JVM still enforces strong typing in its compiled code.