On 10/17/2015 06:46 PM, Stuart Marks wrote:
On 10/10/15 6:55 AM, Remi Forax wrote:
There is an issue with LinkedHashMap (resp LinkedHashSet),
it inherits from HashMap /facepalm/, and static methods are
accessible through class inheritance /facepalm/.
So if LinkedHashMap doesn't declare some methods of(),
LinkedHashMap.of("foo")
will return a HashMap :(
Hi Rémi,
Thanks for pointing this out. I had forgotten about "inheritance" of
static methods. /Facepalm/ indeed. The original proposal (July 2014)
avoided this issue by adding static methods only on interfaces, which
are *not* inherited. When we added statics on concrete classes this
problem returned.
(I view calling an "inherited" class static method to be poor coding
style, but neither javac nor NetBeans warns about it.)
Well, perhaps we won't be adding static factories to the concrete
collections after all, so maybe we can dodge this issue. See messages
downthread.
s'marks
Concrete classes have constructors. With diamonds, if you are lucky. ;-)
Why not adding some constructors like:
public class ArrayList<E> {
// existing
public ArrayList(int initialCapacity)
public ArrayList()
public ArrayList(Collection<? extends E> c)
// new
public ArrayList(E e1)
public ArrayList(E e1, E e2)
public ArrayList(E e1, E e2, E e3)
...
public ArrayList(E... es)
There might be some problems with a few cases like:
List<Integer> list1 = new ArrayList<>(42); // empty list with capacity 42
List<Integer> list2 = new ArrayList<>((Integer) 42); // list with single
element
And consequently some source incompatibilities in rare occasions. But
would that hurt too much?
The question is, and that applies to .of() static methods too, whether
there should be overloads that take 'initialCapacity' too. The
programmer's choice of mutable collection (instead of immutable one) is
probably a consequence of expanding the collection later. So pre-sizing
it to the number of initial elements is rarely optimal.
Mutable collections maybe just need a set of instance methods (defaults
on Collection with covariant overrides on implementations?) that are
used to add a bunch of elements and return 'this', like:
public class ArrayList<E> {
public ArrayList<E> addElements(E e1)
public ArrayList<E> addElements(E e1, E e2)
public ArrayList<E> addElements(E e1, E e2, E e3)
...
public ArrayList<E> addElements(E ... es)
Unfortunately, diamonds are not possible in such arrangement as javac
infers ArrayList<Object> for the following:
ArrayList<String> als = new ArrayList<>().addElements("a", "b",
"c");
Error:(16, 61) java: incompatible types: ArrayList<java.lang.Object>
cannot be converted to ArrayList<java.lang.String>
So it would have to be written explicitly as:
ArrayList<String> als = new
ArrayList<String>().addElements("a", "b", "c");
The question is also whether initialization expressions with mutable
collections and initial sets of elements would really be that frequent
in practice. Currently we can use this:
ArrayList<String> als = new ArrayList<>(Arrays.asList("a", "b",
"c"));
If it can be changed to this:
ArrayList<String> als = new ArrayList<>(List.of("a", "b", "c"));
...it's an improvement.
Regards, Peter