Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java列表<;家长>;和列表<;儿童>;方法_Java_List - Fatal编程技术网

Java列表<;家长>;和列表<;儿童>;方法

Java列表<;家长>;和列表<;儿童>;方法,java,list,Java,List,假设我们有以下情况: public class Parent{ public void setXXX(String XXX); public String getXXX(); } public class Children extends Parent{ .... } public List<Something> cloneList(List<Something> original){ List<Something> newL

假设我们有以下情况:

public class Parent{
     public void setXXX(String XXX);
     public String getXXX();
}

public class Children extends Parent{
 ....
}
public List<Something> cloneList(List<Something> original){
    List<Something> newList=new ArrayList<>();
    for(Something e:original){
        Something newE=new Something();
        newE.setXXX(e.getXXX());
        newList.add(newE);
    }
    return newList;
}
现在我想创建一个名为clone List的方法,如下所示:

public class Parent{
     public void setXXX(String XXX);
     public String getXXX();
}

public class Children extends Parent{
 ....
}
public List<Something> cloneList(List<Something> original){
    List<Something> newList=new ArrayList<>();
    for(Something e:original){
        Something newE=new Something();
        newE.setXXX(e.getXXX());
        newList.add(newE);
    }
    return newList;
}
公共列表克隆列表(列表原件){
List newList=newarraylist();
为了(某物e:原创){
新事物;
newE.setXXX(e.getXXX());
newList.add(newE);
}
返回newList;
}
问题是我们希望克隆列表可以同时应用于
List
List
,那么是否存在适用于“某物”的克隆列表呢

由于Java
集合
集合
不兼容,某些内容不能是“?扩展父项”或“父项”

假设: 1.不希望使用任何序列化方法或反射

  • 我们无法修改父类和子类。这是在第三方Jar中预定义的

  • SuperParent类是不可能的,因为我们无法按照2中的说明修改父类


  • 将克隆列表的签名更改为:

    public <X extends Parent> List<X> cloneList(final List<X> original)
    
    公共列表克隆列表(最终列表原件)
    

    然后它将工作,至少对于方法签名。您可以在内部构造一个
    列表
    ,然后将其强制转换为
    列表
    ,如果需要,可以忽略警告;无法找到运行时类型“X”。

    您不能以这种方式使用泛型,只能使用反射

    对于类型变量
    T
    ,不能使用
    new T()
    。这是因为泛型是一种编译时机制,在运行时使用
    new
    来创建特定的类型对象,而编译器无法在编译时创建对该类型的适当引用。因此,尽管如此:

    new ArrayList<T>();
    

    不是,因为编译器甚至不知道实际的类是什么(即使它只是被定义为
    T extends Parents
    ,也可能是一个在程序编译时还没有编写过的类,比如
    孙子辈
    或其他什么),甚至不知道它是否有无参数构造函数。

    这在Java中是不可能的。看一看

    您可以如下更改您的方法,并使父类扩展SuperParent

    public static <T extends SuperParent> List<T> cloneList(List<T> original, Class<T> type) throws IllegalAccessException, InstantiationException {
        List<T> newList=new ArrayList<>();
        for(T e : original){
            T x = type.newInstance();
            x.setXXX(e.getXXX());
            newList.add(x);
        }
        return newList;
    }
    

    一般来说,您应该能够使用具有此签名的方法:

    public <T extends Parent> List<T> cloneList(List<T> original)
    
    因为不能保证类型参数T存在空构造函数。相反,您需要一个返回正确类型副本的方法。使用完全的类型安全性无法做到这一点,但您可以做到这一点。您可以实现以下方法:

    public Parent Parent.copy();
    public Children Children.copy();
    
    。。。以任何合适的方式,然后像这样写下你的方法:

    public <T extends Parent> List<T> cloneList(List<T> original) {
        List<T> newList = new ArrayList<>();
    
        for (T originalItem : original) {
            newList.add(original.getClass().cast(original.copy()));
        }
    
        return newList;
    }
    
    公共列表克隆列表(列表原件){
    List newList=newarraylist();
    适用于(T原件:原件){
    newList.add(original.getClass().cast(original.copy());
    }
    返回newList;
    }
    

    (请注意,尽管
    Object.getClass()
    的文档化返回类型是
    Class
    ,但它不适用于此目的,但声明返回类型实际上比这更具体,足以使此工作。)

    请考虑这样一个事实,即除非您将问题格式化为代码,否则无法在问题中使用括号。没有任何解决方案可以满足您添加的所有约束条件。要创建类静态未知的对象的忠实副本,需要使用反射或静态已知可用的方法。如果这些类上已经有了copy方法,那么您肯定会在示例代码中使用它。(请注意,
    Object.clone()
    可能达到这个目的,但前提是类
    Parent
    实现了
    Cloneable
    。即使实现了,
    Object.clone()
    ,也可能会有很大的问题。)我更同意关于序列化的建议(或者可怕的
    clone
    ,但忘了我刚才说过的话),而不是基于反思的建议。首先,它假设存在一个无参数构造函数。其次,新副本虽然具有正确的类型,但不会具有原始副本的完整内部状态,这就是为什么首选序列化的原因。
    new T()不仅是因为空构造函数,还因为不能实例化类型变量。但更重要的是,如果类中有任何最终字段,则
    copy()
    方法可能无法正确复制内部状态。需要一个复制构造函数,然后您需要为此使用
    getConstructor(…)
    。@real我建议的
    copy()
    方法不是将状态从一个对象复制到另一个对象,而是返回调用它的对象的副本。它可以用它需要的任何方式来做,包括调用复制构造函数。它不需要使用反射,因为它是对象类的实例方法,因此它知道使用什么构造函数以及如何实例化该类的对象。
    public <T extends Parent> List<T> cloneList(List<T> original) {
        List<T> newList = new ArrayList<>();
    
        for (T originalItem : original) {
            newList.add(original.getClass().cast(original.copy()));
        }
    
        return newList;
    }