• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Devaka Cooray
  • Tim Cooke
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
Saloon Keepers:
  • Piet Souris
Bartenders:

Cruising Along with Java: Var vs Diamond Operator in Modern Java Generics

 
Ranch Hand
Posts: 44
1
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, Venkat Subramaniam !
I’ve recently moved from Java 8 to Java 24, and I see many examples using either the diamond operator (<>) or var when working with generics. In modern Java, which approach do you recommend for real-world projects? What are the main trade-offs between using var and the diamond operator in terms of readability, type inference, and long-term maintainability of the code?
 
Marshal
Posts: 82459
594
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The diamond operator, which you should have been familiar with from its introduction in Java7, is probably incompatible with var. It tells the compiler to use the same actual type parameter as in the declaration, and var hasn't got a declared type. If you look at this example I ran on JShell, you will see it compiles without warning, but there is no type‑safety at all. The javac tool seems to interpret var as plain simple List, without using generics, so I suggest you should avoid var like the plague.

Campbell's JShell wrote:jshell
|  Welcome to JShell -- Version 23.0.1
|  For an introduction type: /help intro

jshell> void foo()
  ...> {
  ...>     var list = new ArrayList<>();
  ...> }
|  created method foo()

jshell> void foo()
  ...> {
  ...>     var list = new ArrayList<>(); list.add("Campbell"); list.add(123); System.out.println(list);
  ...> }
|  modified method foo()

jshell> foo()
[Campbell, 123]

jshell>

If you change the declaration to List<XYZ>, where XYZ is any “real” type other than Object, you will get type‑safety back, and you will see whether you can get the code to compile at all.
Let's see what the JLS (=Java® Language Specification) says about types of variables. I don't think that is the correct section for generics.
Remember you can only use var for local variables. You often see generic declarations for parametersThe following declaration would be legal and maintain type‑safety:-
 
Sheriff
Posts: 22907
132
Eclipse IDE Spring TypeScript Quarkus Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
As you can see, var list = new ArrayList<>() is allowed, but I wouldn't have minded if it weren't. var uses type inference to determine the actual type based on the right-hand side. <> uses type inference to determine the actual type based on the left-hand side. In this case, when neither side wants to make a choice, the compiler does it for you - the resulting type is ArrayList<Object>.
 
Campbell Ritchie
Marshal
Posts: 82459
594
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:. . . I wouldn't have minded if [var list = new ArrayList<>()] weren't. . . .

That seems to me inconsistent with the original buzzwords: Java® was supposed to be “simple”, and that isn't simple. By simple they meant that a programmer could easily remember the rules and what such a construct meant.
 
Author
Posts: 146
16
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi H,

Thank you for the question.

Both var and diamond operator are useful to reduce noise or clutter in code, but they focus on different areas and certainly they both should not be used together.

The diamond operator has been around for a while and it is very useful to avoid repeating type details on both sides of an initialization.

The var is useful when the type information is obvious and the type information if specified will be rather noisy. It is very natural to feel that using var may diminish readability of code. This is very true for those of us who have predominantly programmed in languages like Java where there was not that much of type inference before. However, many languages like Haskell, Scala, Kotlin, C#, and even C++ have had type inference for a while or right form their beginning.

My take on this is as follows:
*If the type information is obvious and is noisy if specified, use var. For those of us who are highly familiar with the codebase, a good variable name and the knowledge we have of the application should help us to quickly know what the type is without having to be mentioned explicitly.
*For those of us new to the codebase or at times when we need a really look at the type, most IDEs will let us hover over the variable name and see its full type. Thus, the type is not hidden from us in reality. It is just not there staring at us and we can look up with little effort if and when we feel a need.
*If the type detail is not obvious or if the type inference will not be correct, given insufficient context, then do not use var.

If you're not convinced, then don't force yourself to use it. May be give it a shot, in unit tests, and see if you get comfortable with it over time, knowing that this can be useful but takes getting used to.

Regards,

Venkat
reply
    Bookmark Topic Watch Topic
  • New Topic