2015-07-29 1 views
3

У меня есть этот код:Как создать массив элементов, чьи записи имеют общие поля?

import java.util.*; 
import java.lang.*; 
import java.io.*; 

class Main{ 
    public static void main (String[] args){ 
     Foo<String> foo = new Foo<String>(1000); 
    } 
} 

class Foo<Key extends Comparable<Key>>{ 
    private Entry[] a; 
    private class Entry{ 
     Key key; 
    } 
    public Foo(int size){ 
     a = (Entry[])new Object[size]; // <- this is the problem 
    } 
} 

, когда я скомпилировать его, я получаю сообщение об ошибке, говоря:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LFoo$Entry; 
at Foo.<init>(Main.java:17) 
at Main.main(Main.java:7) 

Я пробовал:

import java.util.*; 
import java.lang.*; 
import java.io.*; 

class Main{ 
    public static void main (String[] args){ 
     Foo<String> foo = new Foo<String>(1000); 
    } 
} 

class Foo<Key extends Comparable<Key>>{ 
    private Entry[] a; 
    private class Entry{ 
     Key key; 
    } 
    public Foo(int size){ 
     a = new Entry[size]; 
    } 
} 

Но тогда я получил сообщение об ошибке сказав :

Main.java:17: error: generic array creation 
     a = new Entry[size]; 
      ^

Возможно ли создать этот массив?

ответ

2

Ну, на самом деле вы можете через reflection:

public class Main { 
    public static void main(String[] args) { 
     Foo<String> foo = new Foo<String>(1000); 
     foo.a[0] = foo.new Entry(); 
     foo.a[0].key = "ss"; 
    } 
} 

class Foo<Key extends Comparable<Key>> { 
    public Entry[] a; 

    public class Entry { 
     Key key; 
    } 

    public Foo(int size) { 
     a = (Entry[]) java.lang.reflect.Array.newInstance(Entry.class, size); 
    } 
} 
+0

Почему Java не может это сделать по умолчанию? Звучит как боль, которую нужно бросить и написать этот длинный изгиб метода. – Pavel

+0

вы всегда можете сделать 'import java.lang.reflect;' и написать простой '... Array.newInstance (...' – Andremoniy

1

Это потому, что Generics don't cope very well with arrays (при компиляции).

Вы должны лучше использовать некоторые коллекции, вместо:

class Foo<Key extends Comparable<Key>> { 
    private List<Entry> a; 

    private class Entry { 
     Key key; 
    } 

    public Foo(int size) { 
     a = new ArrayList<Entry>(size); 
    } 
} 
+0

Как насчет 'java.lang.reflect.Array.newInstance'? – Andremoniy

+0

Да, подход с Reflection хорош, но я предпочел бы использовать коллекцию вместо того, чтобы делать такие обходные пути. :) –

+0

Может быть, он должен * использовать массивы, мы не знаем – Andremoniy

1

Я согласен с kocko, что вы должны использовать некоторые Collection вместо массивов. Но, к конкретному моменту, это компилируется и работает для меня. Это просто отталкивает ответственность за создание массива до метода Array.newInstance. Недостатком является то, что заставляет бросание

class Foo<Key extends Comparable<Key>>{ 
    private Entry[] a; 
    private class Entry{ 
     Key key; 
    } 
    public Foo(int size){ 
     a = (Entry[])Array.newInstance(Entry.class,size); 
    } 
} 
+0

Я первый :) – Andremoniy

+0

@Andremoniy История моей жизни. :П – MadConan

0

Будучи внутренний класс, то Entry типа находится в пределах объема параметра Key типа, объявленного в классе вмещающей. Другими словами, Entry также является общим.

Вы можете использовать

a = (Entry[]) new Foo<?>.Entry[size]; 

или сырой эквивалент (который я не рекомендую)

a = (Entry[]) new Foo.Entry[size]; 

Этот тип array creation объясняется в JLS

ArrayCreationExpression: 
    new ClassOrInterfaceType DimExprs [Dims] 

заявив

Это ошибка времени компиляции, если ClassOrInterfaceTypeне означает reifiable типа (§4.7).

, где reifiable type является

Типа является reifiable тогда и только тогда, когда одно из следующих условий:

  • Это относится к типу декларации неуниверсального класса или интерфейса.
  • Это параметризованный тип, в котором все аргументы типа являются неограниченными подстановочными знаками (§4.5.1).
  • Это необработанный тип (§4.8).
  • Это примитивный тип (§4.2).
  • Это тип массива (§10.1), тип элемента которого можно повторно идентифицировать.
  • Это вложенный тип, где для каждого типа T, разделенного «.», T сам по себе можно отменить.

Используя параметризацию с групповым символом или необработанного типа, мы можем получить выражение создания массива, представленный выше.

Смежные вопросы