简体   繁体   English

如何将类名传递给抽象超类构造函数?

[英]How to pass in a class name in to abstract superclass constructor?

This is based off my last question Why am i getting a class cast exception(with generics, comparable)? 这是基于我的最后一个问题, 为什么我会收到类强制转换异常(具有泛型,可比)?

Here is my design again. 这又是我的设计。 I have an abstract super class, AbstractArrayList, and two concrete subclasses that extend it, sorted and unsorted array list. 我有一个抽象超类AbstractArrayList和两个扩展它的具体子类,即已排序和未排序的数组列表。

Here's AbstractArrayList which manages the actual data because it needs to for the already implemented methods. 这是AbstractArrayList,它管理实际数据,因为它需要已实现的方法。

public abstract class AbstractArrayMyList<E> implements MyList<E> {
        protected E[] elementData;
       .....
}

Here is the declaration for ArrayListSorted, which extends AbstractArrayMyList 这是ArrayListSorted的声明,它扩展了AbstractArrayMyList

public class ArrayListSorted<E extends Comparable<E>> extends AbstractArrayMyList<E> 

And the lines of test code that caused the exception 以及导致异常的测试代码行

    ArrayListSorted<Integer> toTestInteger = new ArrayListSorted<Integer>()
    toTestInteger.insert(0);
    assertEquals(toTestInteger.get(0).intValue(), 0);

And the actual exception itself 和实际的异常本身

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
    at myarraylist.ArrayListSorted.getIndex(ArrayListSorted.java:38)

ArrayListSorted - java line 38 is inside this method ArrayListSorted-此方法内包含Java第38行

public int getIndex(E value) {
      ....
     line 38 - if      (value.compareTo(elementData[mid]) < 0)  hi = mid - 1;

The response I got from the question clarified what the exception was caused by. 我从问题中得到的答复阐明了异常是由什么引起的。 When I tried making this call 当我尝试拨打此电话时

value.compareTo(elementData[mid]) < 0

value was of the correct type because the extends part will narrow the type object to Comparable type. 值的类型正确,因为扩展部分会将类型对象范围缩小为可比较类型。 However the JVM which runs the java bytecode, will only recognize the elementData array as an object array so when I am trying to cast elementData[mid] to Comparable, it's not actually of Comparable type. 但是,运行Java字节码的JVM仅将elementData数组识别为对象数组,因此当我尝试将elementData [mid]转换为Comparable时,它实际上不是Comparable类型。

The solution that chrylis gave me in the other question was to have a constructor in the AbstractArrayList that will construct the right typed array chrylis在另一个问题中给我的解决方案是在AbstractArrayList中有一个构造函数,该构造函数将构造正确的类型化数组

protected AbstractArrayMyList(Class<E> clazz) {
        this.elementClass = clazz;
        this.elementData = Array.newInstance(clazz, INITIAL_SIZE);
}

I am trying to call this constructor in my sorted array list subclass, with 我试图在我的排序数组列表子类中调用此构造函数,

public class ArrayListSorted<E extends Comparable<E>> extends AbstractArrayMyList<E> 
       public ArrayListSorted() {
             super(Class.forName(("E"));
        }
   ...

Syntax I got from this thread - Passing a class as an argument to a method in java 我从该线程获得的语法- 将类作为参数传递给Java中的方法

However I get a compiler error - The constructor AbstractArrayMyList(Class) is undefined. 但是我遇到了编译器错误-构造函数AbstractArrayMyList(Class)未定义。 Does anyone know what the issue is? 有人知道这个问题是什么吗? I defined that same constructor that chrylis provided me in my question in AbstractArrayList that takes in a class instance. 我定义了与chrylis在我的问题中的AbstractArrayList中提供给我的同一个构造函数,该构造函数接受一个类实例。

If you need the concrete class for a Parameter, you have to specify it. 如果需要Parameter的具体类,则必须指定它。 There is no way to derive it from the type parameter E . 无法从类型参数E派生它。

This applies to your ArrayListSorted() constructor. 这适用于ArrayListSorted()构造函数。 If you want to keep ArrayListSorted generic (with a type Parameter), then you can only pass the Class object along. 如果要保持ArrayListSorted通用(带有Parameter类型),则只能传递Class对象。 If you want to make it specific, you can just specify the parameter and the class. 如果要使其特定,则只需指定参数和类。

In that case I would use a concrete class name like: 在这种情况下,我将使用一个具体的类名称,例如:

public class ArrayListSorted<E extends Comparable<E>>
  extends AbstractArrayMyList<E> {
   public ArrayListSorted(Class<E> cls) {
         super(cls);
    }
...

public IntArrayListSorted extends ArrayListSorted<Integer> {
  public IntArrayListSorted() {
    super(Integer.class);
  }
...

As you can see, when you specify the type parameter ( ... extends ArrayListSorted<Integer> ) it will be defined as Integer, and then the constructor also expects a Class<Integer> : ( super(Integer.class) ). 如您所见,当您指定类型参数( ... extends ArrayListSorted<Integer> )时,它将被定义为Integer,然后构造函数还需要Class<Integer> :( super(Integer.class) )。

One option is, to use a common interface as the implementation, so you can have: 一种选择是,使用公共接口作为实现,因此您可以:

public class ArrayListSorted<E extends Comparable<E>> extends AbstractArrayMyList<Comparable>
{
    public ArrayListSorted()
    {
        super(Comparable.class);
    }
}

No, not literally E , but the class you're using for E . 不,不是字面上的E ,而是您用于E的类。 See the constructor for EnumMap : 请参见EnumMap的构造函数:

new EnumMap<>(KeyEnum.class)

You get the error "The constructor AbstractArrayMyList(Class) is undefined" because you don't have such a constructor. 您收到错误“构造函数AbstractArrayMyList(Class)未定义”,因为您没有这样的构造函数。

public AbstractArrayMyList(Class<E> clazz)
{
    elementData=(E[])Array.newInstance(clazz);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM