0

When I use deepEquals of two empty list it return true even that two lists are of different types. I know that the lists only is of different types while compiling and not runtime.

But is there opportunity of annotates the field or something familiar?

So this what I want:

List<Foo> fooList = []
List<Boo> booList = []

DeepEquals.deepEquals(fooList, booList) //I want it to return false, as the list differs on type

Doing runtime the list appears as ArrayList without typing

Dasma
  • 1,023
  • 13
  • 34
  • Consider that `equals()` for collection classes usually doesn't care about the actual class at all. This is a design choice so that an `ArrayList` and `LinkedList` containing the same elements in the same order are considered equal. – Kayaman Aug 01 '18 at 08:39
  • That I get :) But I am looking for a solution :) – Dasma Aug 01 '18 at 08:41
  • Just curious: Why would you need this? What is the actual code that uses the comparison result? You'd need to keep track of the corresponding `Class` values to distinguish between the two run-time. – Mick Mnemonic Aug 01 '18 at 08:42
  • It is used to bind some errors. Before it wasn't a problem, as the validator had the exact same object. But after converting the validator to a web service the json answer is converted to a new object. DeepEquals.deepEquals helps me the must of the way, but a validate error on a empty list is hard ;) – Dasma Aug 01 '18 at 08:46
  • 2
    This question (https://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens) seems relevant. The top answer explains that the code compiles into `List fooList = []` and `List barList = []` so the two empty lists are actually equal. – Trebla Aug 01 '18 at 13:44
  • 2
    As Trebla says there is no way to know the original parameter type. This is Java type erasure at work: https://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens. At runtime nothing knows the original parameter types. So until Java gets generic reification (it has been discussed but is a hard problem to retrofit) then I'm afraid you're out of luck. – Steve Sowerby Aug 01 '18 at 18:30
  • @SteveSowerby can I make you write the exact same answer as a real "answer" so I can give you points ;) – Dasma Aug 02 '18 at 12:09
  • @Dasma - Now done. – Steve Sowerby Aug 04 '18 at 11:33

1 Answers1

1

There is no solution for this right now in Java or Groovy. You are seeing Java type erasure at work. It was a decision made for things to work that way when generics were added to Java back with Java 1.5.

Basically the compiled class is List. And each field is an instance of that type and are effectively both List<Object> at runtime. The information abut the parameter type is simply not available any longer. A fuller explanation of type erasure can be found here: Java generics type erasure: when and what happens?

Other runtimes such as .NET do have reified types, meaning List<Foo> and List<Bar> are two separate types. Both approaches have their pros and cons.

There has been some discussion and work for the JVM to have something similar in the future. Some of the talks at the JVM Language Summit (JVMLS) show that John Rose and others have been considering template classes and type species to try and solve this problem. So List would be the class but there could be a species for each of List<Foo> and List<Bar>. But AFAIK that is several years away, if it ever arrives.

Steve Sowerby
  • 1,136
  • 1
  • 7
  • 7