[ 
https://issues.apache.org/jira/browse/COLLECTIONS-747?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17034241#comment-17034241
 ] 

Walter Laan edited comment on COLLECTIONS-747 at 2/11/20 8:34 AM:
------------------------------------------------------------------

No, you will need the actual array Class to make a copy. See 
java.util.ArrayList#toArray() which return Object[] and toArray(T[]) which 
creates a copy. Or you could use the class from a key value, but that won't 
work if all of them are null, which is not forbidden as far as I checked.

For example, if want to keep the minimum of two keys, you have to do:
{code:java}
    @SafeVarargs
    public MultiKey(K key1, K key2, K... keys) {
        int length = keys.length + 2;
        @SuppressWarnings("unchecked") // cast is correct because 
K[].getClass() is passed
        K[] tmpKeys = (K[]) Arrays.copyOf(keys, keys.length + 2, 
keys.getClass());
        for(int i = length - 1; i > 1; i--) {
            tmpKeys[i] = tmpKeys[i - 2];
        }
        tmpKeys[0] = key1;
        tmpKeys[1] = key2;

        this.keys = tmpKeys;
    }

// which then allows null keys, though need to specify type instead of just 
diamond (<>)

MultiKeyClassCastException[] keys = new MultiKey<>(key1, key2).getKeys();
MultiKeyClassCastException[] keys2 = new MultiKey<>(key1, key2, key3).getKeys();
MultiKeyClassCastException[] keys3 = new 
MultiKey<MultiKeyClassCastException>(null, null).getKeys();
 {code}
[https://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java]
 [https://softwareengineering.stackexchange.com/a/331109]


was (Author: wlaan):
No, you will need the actual array Class to make a copy. See 
java.util.ArrayList#toArray() which return Object[] and toArray(T[]) which 
creates a copy. Or you could use the class from a key value, but that won't 
work if all of them are null, which is not forbidden as far as I checked.

For example, if want to keep the minimum of two keys, you have to do:
{code:java}
    @SafeVarargs
    public MultiKey(K key1, K key2, K... keys) {
        int length = keys.length + 2;
        @SuppressWarnings("unchecked") // cast is correct because 
K[].getClass() is passed
        K[] tmpKeys = (K[]) Arrays.copyOf(keys, keys.length + 2, 
keys.getClass());
        for(int i = length - 1; i > 1; i--) {
            tmpKeys[i] = tmpKeys[i - 2];
        }
        tmpKeys[0] = key1;
        tmpKeys[1] = key2;

        this.keys = tmpKeys;
    }

// which then allows null keys, though need to specify type instead of just 
diamond (<>)

        MultiKeyClassCastException[] keys = new MultiKey<>(key1, 
key2).getKeys();
        MultiKeyClassCastException[] keys2 = new MultiKey<>(key1, key2, 
key3).getKeys();
        MultiKeyClassCastException[] keys3 = new 
MultiKey<MultiKeyClassCastException>(null, null).getKeys();
 {code}
[https://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java]
[https://softwareengineering.stackexchange.com/a/331109]

> MultiKey.getKeys class cast exception
> -------------------------------------
>
>                 Key: COLLECTIONS-747
>                 URL: https://issues.apache.org/jira/browse/COLLECTIONS-747
>             Project: Commons Collections
>          Issue Type: Bug
>          Components: KeyValue
>    Affects Versions: 4.4
>            Reporter: Walter Laan
>            Priority: Major
>
> When using an non-array constructor of MultiKey, an Object[] is created, 
> which cannot be cast to a K[]
> {code}
> import org.apache.commons.collections4.keyvalue.MultiKey;
> public class MultiKeyClassCastException {
>     public static void main(String[] args) {
>         MultiKeyClassCastException key1 = new MultiKeyClassCastException();
>         MultiKeyClassCastException key2 = new MultiKeyClassCastException();
>         MultiKeyClassCastException[] keys = new MultiKey<>(key1, 
> key2).getKeys();
>     }
> }
> // running gives (same error if in module):
> Exception in thread "main" java.lang.ClassCastException: class 
> [Ljava.lang.Object; cannot be cast to class [LMultiKeyClassCastException; 
> ([Ljava.lang.Object; is in module java.base of loader 'bootstrap'; 
> [LMultiKeyClassCastException; is in unnamed module of loader 'app')
>       at MultiKeyClassCastException.main(MultiKeyClassCastException.java:8)
> {code}
> AFAIK, the only way to fix this (with source compatibility), is to only have 
> a varargs constructors. but I think this breaks binary compatibility though 
> and cannot be used with the existing constructors.
> {code}
>     @SafeVarargs
>     public MultiKey(K... keys) {
>         this.keys = keys;
>     }
> {code}
> Workaround is to use array constructor with correct typed array or 
> {code}Object[] keys = multiKey.getKeys();{code} explicitly.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to