2017-01-18 5 views
2

Ich erhalte ClassCastException. Ich folgte dieser Antwort, verstand es aber nicht richtig. Cast Object to Generic Type for returning
BubbleSort.javaGenerische Klassenmethode, die einen Wert zurückgibt

import java.util.ArrayList; 
import java.util.List; 

public class BubbleSort<T extends Number> { 

    public List<T> list; 

    @SuppressWarnings("serial") 
    public BubbleSort() { 
     list = new ArrayList<T>() { 
     }; 
    } 

    public void add(T obj) { 
     list.add(obj); 
    } 

    public void sort() { 
     for (int i = 0; i < list.size(); i++) { 
      for (int j = 0; j < list.size() - 1; j++) { 
       if (list.get(j).intValue() > list.get(j + 1).intValue()) { 
        T swapElement = list.get(j); 
        list.set(j, list.get(j + 1)); 
        list.set(j + 1, swapElement); 
       } 
      } 
     } 
    } 

    public <T> T getArray(Class<T> clazz){ 
     T[] returnArray = (T[]) list.toArray(); 
     return clazz.cast(returnArray); 
} 

} 

MainPorgram.java

import java.lang.reflect.Array; 


public class MainProgram { 

    public static void main(String args[]){ 
     BubbleSort<Integer> bubbleSort = new BubbleSort<>(); 
     bubbleSort.add(new Integer(1)); 
     bubbleSort.add(new Integer(2)); 
     bubbleSort.add(new Integer(6)); 
     bubbleSort.add(new Integer(5)); 
     bubbleSort.add(new Integer(4)); 
     bubbleSort.add(new Integer(3)); 
     Class<Integer[]> intArrayType = (Class<Integer[]>) Array.newInstance(Integer.TYPE, 0).getClass(); 
     Integer[] sortedArray = (Integer[]) bubbleSort.getArray(intArrayType); 
     for(int i = 0 ; i < sortedArray.length; i++){ 
      System.out.println(sortedArray[i]); 
     } 
    } 

} 

Console

Exception in thread "main" java.lang.ClassCastException: Kann nicht werfen [Ljava.lang .Objekt; [I bei java.lang.Class.cast (Unknown Source) bei BubbleSort.getArray (BubbleSort.java:32) bei MainProgram.main (MainProgram.java:15)

+1

_ "hat es nicht richtig gemacht" _ ist ungenügend. Es wird erwartet, dass Sie den Stack-Trace veröffentlichen und angeben, welche Zeile in Ihrem Programm die Ausnahme auslöst. Erzählen Sie uns auch, was Sie getan haben, um das Problem zu beheben. Hast du den Code in deinem Debugger durchgegangen? –

+0

Hier sind so viele Dinge falsch. – shmosel

+0

'(BubbleSort.java:32)' Dies bedeutet, dass der Fehler in Zeile 32 von BubbleSort.java auftritt. Welche Linie ist das? –

Antwort

0

Sie haben mehrere Probleme.

Das Hauptproblem ist, dass list.toArray() eine Object[] zurückgibt, und Sie können es nicht auf ein Array eines anderen Typs umwandeln. Sie sollten <T> T[] toArray(T[] a) verwenden, um ein Array des richtigen Typs zu erhalten.

Ein anderes Problem mit Ihrem Code war, dass Ihr generischer Parameter, der in der Methode <T> T getArray(Class<T> clazz) deklariert wurde, den generischen Parameter desselben Namens verbirgt, der in der Klassenebene deklariert wurde (class BubbleSort<T extends Number>).

Hier ist eine vorgeschlagene Update, das funktioniert:

public T[] getArray(Class<T> clazz) { 
    return (T[]) list.toArray((T[])Array.newInstance (clazz, list.size())); 
} 

.... 

Integer[] sortedArray = bubbleSort.getArray(Integer.class); 
+0

Könnte auch die Listenlänge überschreiten. Außerdem sollte die äußere Besetzung in 'getArray()' nicht notwendig sein. – shmosel

+0

@shmosel Oh, Sie haben Recht. Danke – Eran

+0

@Eran Danke, Alter! Ich hab es geschafft – user6556461

1

Kann werfen [Ljava.lang.Object; nicht zu [I bei ...

Die Nachricht kann Sie verwirren. Hier bedeutet [Ljava.lang.Object; eigentlich der Typ Object[] und [I bedeutet int[]. Dies sind Java Typ-Signaturen, die nach https://stackoverflow.com/a/8066268/224671 decodiert werden können.


So wird die Fehlermeldung beschweren Sie eine Object[] zu einem int[] zu werfen versuchen. Der einzige Ort, wo man auf den int Typ bezeichnet ist diese Zeile:

Class<Integer[]> intArrayType = 
      (Class<Integer[]>) Array.newInstance(Integer.TYPE, 0).getClass(); 

Das Problem ist, Sie verwenden Integer.TYPE die die Art der int zurückkehrt, so dass die Klasse, die Sie wird Class<int[]> sein bekommen. Um die tatsächliche Integer-Klasse zu verwenden, schreiben Sie:

Class<Integer[]> intArrayType = 
      (Class<Integer[]>) Array.newInstance(Integer.class, 0).getClass(); 
    //             ^~~~~ 

(Siehe Difference between Integer.class and Integer.TYPE für den Unterschied.)

Beachten Sie, dass, da Sie bereits wissen, dass Sie mit Integer[] Klasse beschäftigen, werden Sie tun müssen, um .getClass() nicht nennen reicht das:

Class<Integer[]> intArrayType = Integer[].class; 

Aber das ist immer noch falsch, zB in

public <T> T getArray(Class<T> clazz){ 
    T[] returnArray = (T[]) list.toArray(); 

Sie werden behaupten, ein Integer[][] (und mehr Probleme, die ich werde nicht im Detail gehen) zu bekommen ... Siehe @Eran's answer für die richtige Lösung.

+0

Sie haben nur einen Teil des Problems angesprochen. Es gibt immer noch 'Object []' zurück. – shmosel

+0

Dies ändert nur den Fehler in 'Kann nicht [Ljava.lang.Object; zu [Ljava.lang.Integer; ' – Eran

+0

Diese letzte Änderung ist falsch. Es ist wahr, dass 'T []' 'Integer [] []' wäre, aber wegen der Art des Löschens wird der Cast ignoriert. Das Problem liegt in der nächsten Zeile, wo 'list.toArray()' [gibt 'Object []'] zurück (https://docs.oracle.com/javase/8/docs/api/java/util/List.html) # toArray--), die nicht in 'Integer []' umgewandelt werden können. – shmosel

2

Es gibt ziemlich viel Verwirrung und falsche Annahmen in Ihrem Code. Statt sie alle zu beschreiben (einige wurden in anderen Antworten behandelt), schlage ich Ihnen einen einfacheren Arbeitsansatz vor, wenn Sie auf Java 8 sind:

Verwandte Themen