262
votes

Coming from a C and C++ background, I found judicious use of typedef to be incredibly helpful. Do you know of a way to achieve similar functionality in Java, whether that be a Java mechanism, pattern, or some other effective way you have used?

12
typedef can be used or many things, good and bad, though not everyone agrees on which is which. Would you mind saying which aspects of typedef you think are valuable? That way we can either tell you how to get similar effects in Java or why it's something you don't want to do in Java. The collection of answers below each assumes you are talking about the author's favorite (or most-hated) use.PanCrit
I like to typedef native types if I might later turn it into a class. typedef IndexT int; for example. Later, if I want IndexT to be a class, I just implement it and remove the typedef. It helps with information hiding.JR Lawhorne
I'm not sure what the downsides of this are, but: public interface ScopeFactory { <Scope extends Map<String, Object>> Scope create(...) throws Exception; }ScootyPuff
You might like Scala stackoverflow.com/a/21223102/203968oluies

12 Answers

119
votes

Java has primitive types, objects and arrays and that's it. No typedefs.

106
votes

If this is what you mean, you can simply extend the class you would like to typedef, e.g.:

public class MyMap extends HashMap<String, String> {}
14
votes

There is no typedef in java as of 1.6, what you can do is make a wrapper class for what you want since you can't subclass final classes (Integer, Double, etc)

9
votes

As others have mentioned before,
There is no typedef mechanism in Java.
I also do not support "fake classes" in general, but there should not be a general strict rule of thumb here:
If your code for example uses over and over and over a "generic based type" for example:

Map<String, List<Integer>> 

You should definitely consider having a subclass for that purpose.
Another approach one can consider, is for example to have in your code a deceleration like:

//@Alias Map<String, List<Integer>>  NameToNumbers;

And then use in your code NameToNumbers and have a pre compiler task (ANT/Gradle/Maven) to process and generate relevant java code.
I know that to some of the readers of this answer this might sound strange, but this is how many frameworks implemented "annotations" prior to JDK 5, this is what project lombok is doing and other frameworks.

5
votes

Really, the only use of typedef that carries over to Javaland is aliasing- that is, giving the same class multiple names. That is, you've got a class "A" and you want "B" to refer to the same thing. In C++, you'd be doing "typedef B A;"

Unfortunately, they just don't support it. However, if you control all the types involved you CAN pull a nasty hack at the library level- you either extend B from A or have B implement A.

4
votes

Perhaps this could be another possible replace :

@Data
public class MyMap {
    @Delegate //lombok
    private HashMap<String, String> value;
}
3
votes

As noted in other answers, you should avoid the pseudo-typedef antipattern. However, typedefs are still useful even if that is not the way to achieve them. You want to distinguish between different abstract types that have the same Java representation. You don't want to mix up strings that are passwords with those that are street addresses, or integers that represent an offset with those with those that represent an absolute value.

The Checker Framework enables you to define a typedef in a backward-compatible way. I works even for primitive classes such as int and final classes such as String. It has no run-time overhead and does not break equality tests.

Section Type aliases and typedefs in the Checker Framework manual describes several ways to create typedefs, depending on your needs.

1
votes

Kotlin supports type aliases https://kotlinlang.org/docs/reference/type-aliases.html. You can rename types and function types.

-1
votes

In some cases, a binding annotation may be just what you're looking for:

https://github.com/google/guice/wiki/BindingAnnotations

Or if you don't want to depend on Guice, just a regular annotation might do.

-5
votes

You could use an Enum, although that's semantically a bit different than a typedef in that it only allows a restricted set of values. Another possible solution is a named wrapper class, e.g.

public class Apple {
      public Apple(Integer i){this.i=i; }
}

but that seems way more clunky, especially given that it's not clear from the code that the class has no other function than as an alias.

-7
votes

Typedef allows items to be implicitly assigned to types they are not. Some people try to get around this with extensions; read here at IBM for an explanation of why this is a bad idea.

Edit: While strong type inference is a useful thing, I don't think (and hope we won't) see typedef rearing it's ugly head in managed languages (ever?).

Edit 2: In C#, you can use a using statement like this at the top of a source file. It's used so you don't have to do the second item shown. The only time you see the name change is when a scope introduces a name collision between two types. The renaming is limited to one file, outside of which every variable/parameter type which used it is known by its full name.

using Path = System.IO.Path;
using System.IO;
-14
votes

There is no need for typedef in Java. Everything is an Object except for the primitives. There are no pointers, only references. The scenarios where you normally would use typedefs are instances in which you create objects instead.