2013-05-20 1 views
0

Так что я кодирование до общего списка смежности и мой код не содержат ошибок компиляции, но когда я запускаю свои тесты, я получаю то же ошибку во время выполнения по всем направлениям:Java Дженерик Причинение класса Cast Ошибки

java.lang.ClassCastException: [[Ljava.lang.Object; cannot be cast to [[Lds.Graph.Edge; 
    at ds.TheAdjacencyMatrix.AdjacencyMatrix.<init>(AdjacencyMatrix.java:86) 
    at ds.TheAdjacencyMatrix.AdjacencyMatrix.<init>(AdjacencyMatrix.java:63) 
    at ds.TheAdjacencyMatrix.AdjacencyMatrix.<init>(AdjacencyMatrix.java:73) 
    at ds.Graph.Test.TheAdjacencyMatrixTest.testAddVertex(TheAdjacencyMatrixTest.java:33) 

ошибка в конструкторе на линии, где я бросил массив 2d объект Е [] [] Тип

Соответствующий код для матрицы смежности ::

public class AdjacencyMatrix<T, E extends Edge> 
     implements AdjacencyMatrixInterface<T, E>, Graph<T, E> { 

    //~Constants---------------------------------------------- 
    private static final int DEFAULT_SIZE = 10; 

    //~Data Fields-------------------------------------------- 
    /** 
    * Int matrix that holds edge weights in weighted graphs. 
    * A 1 in a directed graph indicates an edge, a 0 indicates no edge. 
    */ 
    private E[][] matrix; 

    /** 
    * Array of elements contained in the graph. 
    * Elements correspond to the same indices as they do in the adjacency matrix of edges. 
    * 
    * i.e. matrix[4][5] is an edge from 4 to 5, 
    * elements[4] is the element at 4, elements[5] is the element at 5 
    */ 
    private T[] elements; 

    /** 
    * The maximum number of vertices in the adjacency matrix. 
    */ 
    private int size; 

    /** 
    * The current number of vertices in the graph. 
    */ 
    private int numVertices; 

    /** 
    * Indicates whether the graph is directed or not. True if directed, false otherwise. 
    */ 
    private boolean directed; 

    //~Constructors-------------------------------------------- 
    /** 
    * Initializes the adjacency matrix to a size of 10. 
    * Which means there are 10 vertices in the graph. 
    */ 
    public AdjacencyMatrix() { 

     this(DEFAULT_SIZE); 
    } 

    /** 
    * Initializes the adjacency matrix to a size of 10. There will be 10 vertices in the graph. 
    * 
    * @param directed true if the graph is to be a directed graph, false otherwise. 
    */ 
    public AdjacencyMatrix(boolean directed) { 

     this(); 
     this.directed = directed; 
    } 

    /** 
    * Initializes the adjacency matrix to a size of size. 
    * There will be a maximum size of *size* vertices in the graph 
    * 
    * @param size the size of the adjacency matrix. 
    */ 
    @SuppressWarnings("unchecked") 
    public AdjacencyMatrix(int size) { 

     matrix = (E[][]) new Object[size][size]; 
     elements = (T[]) new Object[size]; 

     this.size = size; 
     numVertices = 0; 
     directed = false; 
    } 

А класс Край является абстрактный класс е-код здесь:

package ds.Graph; 

/** 
* An abstract Edge class which has methods 
* getWeight() 
* and 
* setWeight(int weight). 
* Used for a Graph data structure to abstract 
* out the edges. 
* 
* 
* 
*/ 
public abstract class Edge implements Comparable<Edge> { 

    /** 
    * Sets the weight of the edge to the passed in weight. 
    * 
    * @param weight the weight of the edge. 
    */ 
    public abstract void setWeight(int weight); 

    /** 
    * Gets the weight of the edge. 
    * 
    * @return the edge weight. 
    */ 
    public abstract int getWeight(); 
} 

EDIT ::

Так что это строка кода, которая устанавливает ошибки во время выполнения. IntEdge - это всего лишь объект, наследующий от Edge, который содержит целое число.

AdjacencyMatrixInterface<String, IntEdge> matrix = new AdjacencyMatrix<String, IntEdge>(false); 
+3

Мораль истории: не используйте '@SuppressWarnings (« unchecked »)', не понимая, зачем вам это нужно. – prunge

+1

Java Generics не вызывает эту ошибку. Вы. – EJP

ответ

2

Простые изменения, которые выравнивают к

matrix = (E[][]) new Edge[size][size]; 

E стирается, чтобы его верхняя граница внутри класса. В этом случае верхняя граница E равна Edge. Поэтому он попытается отбросить до Edge[][].

Кроме того, вы должны убедиться, что matrix и elements не подвергается воздействию извне, как E[][] и T[] соответственно, так как они не являются на самом деле из этих типов. Но пока вы используете их только в классе, проблем нет.

+0

Проблема в том, что E - абстрактный класс. Я хочу, чтобы иметь возможность определять объекты, которые наследуются от Edge, а затем просто быть в состоянии бросить их в это. Таким образом, я мог либо идти абстрактным классом, либо интерфейсом ... но оба дают мне ту же ошибку. – Ethan

+0

И ждите ... так что Edge [] [] - это то, что кастинг заменяется ... тогда не моя проблема на самом деле, я устанавливаю ссылку какого-либо типа, который наследует от Edge, чтобы ссылаться на массив casted object? – Ethan

1

Проблема в том, что Object [] [] не является экземпляром Edge [] []. Вы не можете бросать свои объекты так.

new Object[][] {} instanceof Edge[][] // => false 

Его наоборот Object [] [] фактически является суперкласс Край [] []

new Edge[][] {} instanceof Object[][] // => true 

Кроме того, согласно Java Language Specification

непосредственного суперкласса Тип массива - объект. Каждый тип массива реализует интерфейсы Cloneable и java.io.Serializable.

Edit:

Кроме того, as Rahul Bobhate pointed out, его лучше использовать Java Collections Framework, так как он был разработан, чтобы использовать дженерики. Все array-based обходные пути - are pretty ugly.

0

Это не правильно, вы должны получать бесконтрольно предупреждения ролей:

matrix = (E[][]) new Object[size][size]; 
     elements = (T[]) new Object[size]; 

Вы должны явно передать экземпляры массива, так как общая информация стираются во время выполнения (что означает в коде во время выполнения при исполнении будет matrix = new Object[][])

Вы можете иметь конструктор, как:

public class AdjacencyMatrix<T, E extends Edge> 
     implements AdjacencyMatrixInterface<T, E>, Graph<T, E> { 
E[][] matrix; 
T[] elements; 
public AdjacencyMatrix(int size, E[][] matrix, T[] elements) { 
     this.matrix = matrix; 
     this.elements = elements; 
    } 
} 
+1

... или использование коллекций вместо массивов поможет здесь и я думаю, – macias

+1

Вы говорите, что «общая информация удаляется во время выполнения», и это правда, но общие типы заменяются их верхними границами, поэтому во время выполнения код становится 'matrix = (Edge [] []) new Object [] []', что приводит к исключению ClassCastException. – herman

0

Вы не можете бросить массив из Object в E. Хотя он будет скомпилирован, он вызовет ClassCastException во время выполнения. Вы можете использовать только совместимые типы ссылок. Поскольку массив из E и массив Object никак не связаны, JVM не сможет отобразить массив из Object в массив из E.

Вы можете использовать List вместо массива.Вы можете определить матрицу как List из List следующим образом:

private List<List<E>> matrix; 
private List<T> elements; 

Вы можете инициализировать matrix в конструкторе легко:

public AdjacencyMatrix(int size) { 

    matrix = new ArrayList<List<E>>(size); 
    for(int i=0; i<size; i++) 
    { 
     t.add(new ArrayList<E>()); 
    } 

    elements = new ArrayList<T>(size); 

    this.size = size; 
    numVertices = 0; 
    directed = false; 
} 

Вы можете получить доступ к элементам внутри списка следующим образом:

E e = matrix.get(0).get(1); 

Это даст вам 2-й элемент в 1-м списке.

+1

"это вызовет ClassCastException во время выполнения" Не обязательно. 'E' будет стерто до верхней границы внутри класса. Если его верхняя граница - «Объект», то в этом выражении не будет «ClassCastException». – newacct

+0

^Не могли бы вы рассказать об этом? Как я могу создать объект верхней границы? – Ethan

-1

Причина в том, что даже если E является подклассом Object, E [] не является подклассом Object []. Массивы имеют иерархию классов и, следовательно, не могут быть переброшены друг в друга.

[Редактировать]

я был неправ (спасибо за комментарий). На самом деле существует иерархия типов для массивов (см. http://etutorials.org/cert/java+certification/Chapter+6.+Object-oriented+Programming/6.5+Completing+the+Type+Hierarchy/). Как правильно указано, вы пытаетесь применить экземпляр супертипа к подтипу, который не будет работать и для других объектов Java.

+1

У вас есть это в обратном порядке - 'E [] []' * является * подклассом 'Object [] []', но простой 'Object [] []' нельзя отнести к стиранию 'E [] [] ', который является' Edge [] [] '. –

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

  • Нет связанных вопросов^_^