260

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?

Matt Ball
  • 332,322
  • 92
  • 617
  • 683
bn.
  • 7,031
  • 7
  • 37
  • 53
  • 6
    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 Jul 28 '09 at 16:47
  • 3
    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 Aug 20 '10 at 01:22
  • 13
    @Alexander - updated link: http://www.ibm.com/developerworks/java/library/j-jtp02216/index.html – Andreas Dolk Aug 01 '11 at 20:20
  • 1
    I'm not sure what the downsides of this are, but: `public interface ScopeFactory { > Scope create(...) throws Exception; }` – ScootyPuff Aug 23 '11 at 13:43
  • 2
    You might like Scala http://stackoverflow.com/a/21223102/203968 – oluies Mar 08 '14 at 18:21
  • [Code examples of Design Patterns in various languages: C#, C++, Go, Java, JavaScript, Python, and Swift.](https://github.com/MilovanTomasevic/Design-Patterns) – Milovan Tomašević Apr 18 '21 at 19:10

12 Answers12

119

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

cletus
  • 578,732
  • 155
  • 890
  • 933
  • 42
    I guess most of people want `typedef` to redefine `boolean` to `bool`. – Tomáš Zato - Reinstate Monica Apr 28 '14 at 12:00
  • 76
    @TomášZato I don't know most people, but in my experience, it's useful for adding semantics like: `typedef int PlayerID` which enables the compiler to make sure PlayerIDs aren't being used interchangeably with other ints, and it also makes code much more readable for humans. Basically, it's like an enum but without a limited set of values. – weberc2 Jan 02 '15 at 23:43
  • 81
    @TomášZato It's also usefull to shorten long types such as `typedef MegaLongTemplateClass IsShorten;`. – Alex Medveshchek Feb 20 '15 at 12:47
  • 38
    @weberc2 "which enables the compiler to make sure PlayerIDs aren't being used interchangeably with other ints" – `typedef` doesn't enable any such thing. It just gives another name for a type. – emlai Dec 16 '15 at 08:24
  • 5
    A 'typedef' is not the same sort of thing as a 'primitive type', 'object' or 'array'. The last three are all types of types, while a typedef is the same as an alias for giving a new name to an existing type. 'Java has primitive types, objects and arrays and that's it.' and 'Java has no typedefs' are both true statements. It's just that the second has nothing to do with the first. – John Gowers Dec 13 '17 at 23:03
  • 11
    Also useful if, for instance, you have some ID of type `int` and you need to change it to `long`, you have to change it in every place in code where you work with the ID. If you had `typedef`, you'd only have to change it in 1 place. – Jardo Jan 02 '18 at 10:15
  • 1
    Also also useful if you want to get compile errors when you try to pass two long arguments in the wrong order - if they have semantic typedefs then you can ensure that they will always be passed in the right order because the caller has to use the same typedefs to declare them. For example, you might have a typedef `long` -> `microdollars` so that the *price* of something and the *amount* you want to buy are passed in the correct order to the `buy` function. – Chris Browne Jul 01 '18 at 09:55
105

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> {}
Zed
  • 53,338
  • 7
  • 71
  • 100
  • 6
    I'd argue whether this is any more anti-pattern than using typedef in C. – Zed Jul 28 '09 at 16:41
  • 22
    It definitely is - `typedef` has none of the problems that article describes for those fake classes (and they are very real). – Pavel Minaev Jul 28 '09 at 17:01
  • 2
    Also, it's not even possible with final classes such as `java.lang.String` – hertzsprung Feb 21 '12 at 20:40
  • 30
    @Andreas_D: your link, fixed: http://www.ibm.com/developerworks/java/library/j-jtp02216/index.html – Janus Troelsen Jan 11 '13 at 22:53
  • you can do that but not simply, because it may require to define the constructor, which is code duplication. – Leonid Mar 06 '13 at 16:52
  • This may be an antipattern in some contexts, but not all. Jython doesn't handle parameterized types, so there's no typesafe way to pass an instance to it without either encapsulating it or subclassing it as shown above. The article calls this an anti-pattern because it inhibits code reuse, but for this purpose (giving Jython a one-time callback), code reuse is undesirable. – Jim Pivarski Aug 13 '13 at 20:56
  • 8
    I like this for the same reason I like typedefs. If you have a container of objects, it is easy to swap container types by changing the typedef. Also, it can abstract the container to the end user (which is sometimes desirable). I would usually do this inside of another class, so then the type becomes more obvious (i.e. MyTree.Branches, where class Branches extends HashSet{}) – Josh Petitt Oct 06 '13 at 16:13
  • 8
    Although the _main_ problem with this approach is that you can't use it with `final` classes. – AJMansfield Apr 08 '14 at 21:24
  • Namespaces are very important. This is a natural way to bend the note to get what you want. – vwvan Jun 16 '14 at 04:26
  • 2
    The exact reason i searched for "typedef in java" is for a HashMap declaration like above. So i can use something like HashMap instead of using generic declaration like this HashMap or without creating and extending Person and Detail classes with String Class. – HarshaXsoad May 19 '16 at 03:21
  • This creates a new type, not a type alias. For example, a function signature modified to accept MyMap can no longer be passed an ordinary HashMap. It also fails to inherit constructors, and has other inheritance-specific shortcomings. – Jeff Schwab Jul 08 '20 at 11:59
14

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)

z -
  • 6,990
  • 3
  • 36
  • 65
  • 7
    The referenced anti-pattern article is based on the assumption that you just want to shorten your typing (which would actually hide the helpful type information). The real use most people want is to disambiguate types and let the compiler do its job for you. See IndexT above. public Invoice fetchInvoiceItem(String, String, String); versus public Invoice fetchInvoiceItem(CustomerId, InvoiceId, InvoiceLineItemId); Explicit types plus Converters/Validators makes programming Web APIs where EVERYTHING starts out as a String a lot safer. – englebart Jan 13 '17 at 14:42
  • 1
    No operator oveloading in java, so it gets ugly – mils Feb 22 '18 at 09:04
9

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.

Yair Zaslavsky
  • 3,987
  • 2
  • 17
  • 25
5

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.

Zack Yezek
  • 181
  • 2
  • 1
  • 15
    Having `typedef` would also be useful to create aliases for invocations of generic types. For example: `typedef A B;` (this may be a special case of what you've described, but it shows the appeal of the idea a little more clearly). – igorrs May 11 '12 at 00:24
  • In my use case, I want to give aliases to primitive types. `real_t` for `double` and `bool` for `boolean`. – Aaron Franke Aug 31 '18 at 05:27
4

Perhaps this could be another possible replace :

@Data
public class MyMap {
    @Delegate //lombok
    private HashMap<String, String> value;
}
shrewquest
  • 461
  • 5
  • 21
  • 2
    Don't you think that this now has a problem because whenever you define `myMap` instance of type `MyMap`, you can operate on actual HashMap only by typing `myMapInstance.value.SomeOperation()` instead of `myMapInstance.SomeOperation()`. This is annoying, isn't it? – mercury0114 Nov 17 '16 at 22:02
  • 2
    you can still do myMapInstance.SomeOperation() - this is what the @Delegate is for – shrewquest Jan 17 '18 at 16:46
  • Note that currently (8/2020) @Delegate is "experimental" in lombok https://projectlombok.org/features/experimental/Delegate ```Current status: negative - Currently we feel this feature will not move out of experimental status anytime soon, and support for this feature may be dropped ...``` – David Gelhar Aug 17 '20 at 13:38
3

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.

mernst
  • 6,276
  • 26
  • 41
1

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

sebnukem
  • 7,217
  • 5
  • 35
  • 45
-1

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.

dzs0000
  • 9
  • 3
-5

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.

Michael Celey
  • 12,087
  • 6
  • 53
  • 60
Steve B.
  • 49,740
  • 11
  • 90
  • 128
-7

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;
Dave McClelland
  • 3,256
  • 1
  • 26
  • 43
Sam Harwell
  • 92,171
  • 18
  • 189
  • 263
  • 24
    "Typedef allows items to be implicitly assigned to types they are not" What? Typedef simply allows you to create another name as an alias for the type. The type is still the exact same, you just get a shorter name for it. It has nothing to do with type inference. -1 – jalf Jul 28 '09 at 16:34
  • @jalf: Actually, type inference is used as the solution to exactly what you're talking about, but I've given another example where you can use a "typedef" to get around a name collision. – Sam Harwell Jul 28 '09 at 16:50
  • 1
    updated link: http://www.ibm.com/developerworks/java/library/j-jtp02216/index.html – Alexander Malakhov Aug 02 '11 at 03:48
  • @AlexanderMalakhov Thanks, I went ahead and updated the answer with your link – Dave McClelland Jul 02 '12 at 12:45
-14

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.

Markus Koivisto
  • 603
  • 3
  • 6
  • 20
    No, the need for typedef still exists if you want a shorter name for a type. Or just if you want to be able to replace the use of one type with another by changing one place in the source code. – jalf Jul 28 '09 at 16:36
  • 1
    The latter hinders readability, since a new programmer will have to look up the definitions of all the types. The OO way is to use polymorphism instead. The source code uses the superclass or the abstract class/interface and the specific type is only changed where the object is created. – Markus Koivisto Jul 28 '09 at 16:39
  • 1
    The most important part of code is making your code readable. Renaming (Duplicating!) a type for shortness has to be the absolutely worst coding concept I've come across in a while! – Bill K Jul 28 '09 at 17:31
  • 30
    @Bill K: meh, say that after you've had to type something like std::map > >::const_iterator a few times. In that case, a name-shortening typedef enhances readability, not hinders it. – Joel Jul 30 '09 at 14:45
  • 1
    Many uses of typedef deal with portability. There is less need for typedef in Java (although I would not agree that there is no need for it) because - for example - int is 32 bits on the one and only platform that Java runs on, the JVM. – Joel Jul 30 '09 at 14:49
  • 24
    Renaming a type can improve readability drastically. What is easier to read and comprehend (and thus more readable:) `UnmodifiableDirectedGraph` or `IncrediblyFancyGraph`? I can always refer to the definition to find out what it's actually about. That way I can also be sure I won't miss `UnmodifiableDirectedGraph` out of sheer boredom. – Aleksandar Dimitrov Mar 03 '11 at 21:31
  • 10
    @AleksandarDimitrov I know that your comment is almost 3 years old as I type this, but I feel it's very important to point out how contrived and unrealistic that example is: none of those class names contains the word `Enterprise`. – Casey Feb 18 '14 at 15:22
  • 5
    Bad names hinder readability. Good names help. Typedefs can help if there is full name is so long that it becomes hard to read or screws up your code formatting. It also would help when interacting with someone else's poorly choosen or ambiguous class names. If you really believe that a typedef is inherently going to make your code unreadable, then you should also believe that you should never use import statements and should always refer to fully qualified class names. – Christopher Barber Mar 04 '14 at 16:07
  • Then what if I want to create a typedef for primitives? – Aaron Franke Aug 31 '18 at 05:30