Why do you use MyObject [] inside, but expose List <MyObject>?

I came across a class that has an immutable property:

MyObject[] allObjs 

The property is initialized as follows:

 List<MyObject> objs = createAllMyObjects(); allObjs = objs.toArray(new MyObject[objs.size()]); 

When it opens through an accessor, this is done as a List:

 public List<MyObject> getAllMyObjects() { return Collections.unmodifiableList(Arrays.asList(allObjs)); } 

Why should a programmer do this? Are there any benefits that I don't know about?

Performance is not a concern, as the objs array will only ever count several tens of elements.

It seems we are spinning in circles.

The class is a kind of factory, so it got a private constructor and provides only static methods (not sure if this could be the cause of insanity).

change

I think my question really is: "Why not just use the internal List<MyObject> allObjs instead of MyObject[] allObjs and return Collections.unmodifiableList (allObjs)?" as this will do the same thing.

+4
source share
9 answers

The only reason I see is “to fail early if misused” (if this design choice was not random and made sense, then the point is that he trusts his specific customers very little).

MyObject[] reified and marked at runtime , but List<MyObject> is not. In the latter, you can colorize links other than MyObject (it, of course, will receive uncontrolled warnings when compiling), which will fail in the future undefined with the ClassCastException point, but it cannot do the same with MyObject[] - which will immediately fail in moment of misuse.

Note that if the clients are pre-created binaries that used this API before it was generated, then no one received unverified warnings, so if this code tries to migrate the code used by the predip clients, it makes sense.

(Another way to achieve the same result is to use List<T> , and also requires Class<T> , so the latter can offer runtime type checks. But this will require, for example, another constructor parameter - existing clients will not automatically use this . ** Update: ** This basically describes the API call mentioned in Sauer's first comment, so no need to reinvent it, just use it :)).

+6
source

There may be several reasons for this:

  • They did not know what they were doing. I'm currently working on code that seems to be written by someone new to Java and new to programming. Unfortunately, it is too common to find poorly designed code than to find good, clean, well-groomed code written by someone who has a clear understanding of the platform. This is partly due to the following point.
  • List changes have been fixed without the need for bulk changes. If the rest of the code uses an array, someone might not want to worry about making all the other changes.
  • While Collections is more of an OO / Java way to do something if this list is static, the array actually works “easier” since they can still be repeated using for(:) as a collection, but available using [] instead of get() . Personally, not a good reason to use arrays, but maybe it's just me.
  • Perhaps they wanted it to be clear that the length of the data is final. If they just used an unmodifiable list, List will still be a means to access the data, and anyone who doesn't pay attention to the rest (hopefully commented out) of the code may try to add to the List , which will result in an UnsupportedOperationException at runtime. Creating an array makes use clear.
+2
source

It seems that the writer intended to return an unchanged copy and did so unnecessarily. I assume that List was selected as the return type, so the clone could be easily created using the MyObject type.

+1
source

There is a good reason not to return a reference to the internal attribute MyObject[] . Through reference changes, you can make the caller into the array.

If there is no reason why the result should be List , you can also return a copy of the array:

 public MyObject[] getAllMyObjects() { MyObject[] result = new MyObject[allObjs.length]; system.ArrayCopy(allObjs, 0, result, 0, result.length); return result; } 

Refresh , after adding to the question: You are right in that if the internal attribute is changed to a list, simplify updating it without the possibility of updating.

The reason the class uses an array instead of a list may be performance. If the array does not change (a lot) during the life of the object and is repeated many times, the array has less overhead than List.

If performance is the reason for using an array, you can prevent the creation of additional objects in the receiver by storing the list for the sole purpose of returning, i.e.:

 allObjsList = Collections.unmodifiableList(createAllMyObjects()); allObjs = allObjsList.toArray(new MyObject[allObjsList.size()]); 

use the allObjs array as before and return the saved list to getter:

 public List<MyObject> getAllMyObjects() { return allObjsList ; } 
+1
source

Let me answer with a joke:

The new Jewish bride makes her first big dinner for her husband and tries her hand in her mom’s recipe, cutting off the frying ends as her mother always did. Hubby thinks the meat is very tasty, but says, "Why you cut the ends is the best part!" She replies: "The way my mother always did this.

Next week they will go to an old house with bubbles, and she is preparing the famous brisket recipe, again cutting off the ends. The young bride is sure that she lacks important information, so she asks her grandmother why she cut the ends off. Grandma says: "Dahlin, this is the only way he fits in the pan!"

Although we certainly can find some arguments to justify any particular decision, in practice this rarely makes any difference, and often there is no reason to make such decisions.

Use the simplest and easiest way to read. Readability is often more important than skill.

+1
source

I see no benefit in using arrays instead of lists. Lists are much more convenient. Maybe the guy just likes working with arrays :)

0
source

I think the reason for this may be that the array is not modifiable. However, you can save the internal list as a list and simply return a copy of it to getter, so the internal list will still not be changed externally.

Or use the "non-modifiable" list returned by Collections.unmodifiableList () ...

In this case, I also see no performance advantages, because the back and forth conversion still takes several cycles.

0
source

Thus, the collection is not modified, i.e. the caller cannot modify the member array. It is not possible to do this with an array so that the encoder copies it to the list.

0
source

In the Java Generics book , the author actually says that since we have Generics, we should use the collection exclusively and should not use the array anymore, Personally, I now try to stay away from arrays, because collections help me remember my intention to use a collection of things, for example . sets vs list as opposed to an array that doesn't really tell me anything about the data.

There is also nothing that I cannot do with collections that I cannot do with an array, with the possible exception of a quick copy (System.arraycopy ())

0
source

Source: https://habr.com/ru/post/1306354/


All Articles