简体   繁体   English

Java-将泛型用于多种类型

[英]Java - Using Generics for multiple Types

I have the following DataSet class where we hold any kind of object. 我有以下DataSet类,我们可以容纳任何类型的对象。 Mostly to transfer objects from the server to the client. 通常是将对象从服务器传输到客户端。 The contents variable can hold any serializable object. contents变量可以保存任何可序列化的对象。 It could be custom written class Objects or java classes like Integer , String etc. 它可以是自定义编写的类Objects或Java类,例如IntegerString等。

I'm trying to convert this into generics. 我正在尝试将其转换为泛型。 How should we go about converting this into Generics at the same time, I would like to make sure that I don't have to change all the containing object class code, since we are even using String and Integer classes within the contents. 我们应该如何同时将其转换为泛型,我想确保不必更改所有包含的对象类代码,因为我们甚至在内容中使用StringInteger类。

I have simplified the class to only show some relevant fields and methods. 我将类简化为仅显示一些相关的字段和方法。

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Vector;

public class DataSet implements Serializable, PropertyChangeListener{

    Hashtable contents = new Hashtable();

    @Override
    public void propertyChange(PropertyChangeEvent arg0) {
        // TODO Auto-generated method stub

    }

    public void addObject(Object obj){
        Vector vector = (Vector)contents.get(obj.getClass());
        if (vector == null){
            vector = new Vector();
            vector.add(obj);
            contents.put(obj.getClass(), vector);
        }
    }

    public Vector getObjects(Class objType){
        if (contents.contains(objType)){
            return (Vector)contents.get(objType);
        }
        else{
            return new Vector();
        }
    }
}

Appreciate your prompt replies. 感谢您的及时答复。 But, after reviewing the three answers below, I felt like I didn't convey the problem correct. 但是,在查看了以下三个答案之后,我觉得我没有正确地传达问题。

To make this the way I want, if I invoke dataset.getObjects(of E type), I should be getting a vector of E type. 为了使这种方式成为我想要的方式,如果我调用dataset.getObjects(E type),我应该得到一个E类型的向量。 I shouldn't be casting into (Vector). 我不应该投向(向量)。 Because I want the contents to be holding Class<E> , and Vector<E> of key value pairs. 因为我希望内容保留键值对的Class<E>Vector<E> If we can do that, then only I could say that this is safe . 如果我们能够做到这一点,那么我只能说这是safe

DataSet ds = new DataSet();
Vector<String> strings = ds.getObjects(String.class);
Vector<Integer> integer = ds.getObjects(Integer.class);
Vector<Employee> employees = ds.getObjects(Employee.class);

First of all, stay away from class Vector , it's obsolete; 首先,远离Vector类,它已经过时了; use ArrayList instead. 使用ArrayList代替。

Here's a simple way to store heterogeneous objects while avoiding explicit casting when retrieving objects. 这是一种存储异构对象,同时避免在检索对象时进行显式转换的简单方法。 I'm sure you can work this model into your solution. 我确定您可以将此模型应用于您的解决方案。

UPDATED , thanks to advice from Paul Bellora . 更新 ,感谢Paul Bellora的建议。

public class DataSet { 

    private Map<Class<?>, List<?>> contents;

    public DataSet(){
       contents = new HashMap<Class<?>, List<?>>();  
    } 

    @SuppressWarnings(value = { "unchecked" })
    public <T> void addObject(Class<T> klass, T object){
        List<T> objectsList = (List<T>)contents.get(klass);
        if (objectsList == null){
            objectsList = new ArrayList<T>();            
            contents.put(klass, objectsList);
        }
        objectsList.add(object);
    }

    @SuppressWarnings(value = { "unchecked" })
    public <T> List<T> getObjects(Class<T> klazz) {
        return contents.containsKey(klazz) ? 
                contents.get(klazz) : Collections.EMPTY_LIST;
    }

    public static <S, T extends Iterable<S>> void print(T list){
        for (Object element : list){
            System.out.println(element);
        }
    }

    public static void main(String[] o){
       DataSet ds = new DataSet();
       ds.addObject(String.class, "save the earth!");
       ds.addObject(String.class, "firing now!");       
       ds.addObject(Integer.class, new Integer(100));
       ds.addObject(Boolean.class, new Boolean(true));

       print(ds.getObjects(String.class));
       print(ds.getObjects(Boolean.class));
       print(ds.getObjects(Integer.class));      
    }
 }

Hope it helps. 希望能帮助到你。

Perhaps this would be sufficient: 也许这就足够了:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.Map;
import java.util.List;

public class DataSet implements Serializable, PropertyChangeListener{

    Map<Class<?>, Vector<Serializable>> contents = new HashMap<Class<?>, Vector<Serializable>>();

    @Override
    public void propertyChange(PropertyChangeEvent arg0) {
        // TODO Auto-generated method stub
    }

    public void <T extends Serializable> addObject(T obj){
        Vector<T> vector = (Vector<T>)contents.get(obj.getClass());
        if (vector == null){
            vector = new Vector<T>();
            contents.put(obj.getClass(), vector);
        }
        vector.add(obj);
    }

    public <T extends Serializable> Vector<T> getObjects(Class<T> objType){
        if (contents.contains(objType)){
            return (Vector<T>)contents.get(objType);
        }
        else{
            return new Vector<T>();
        }
    }
}

I've edited my original post. 我已经编辑了我的原始帖子。 Indeed, as pointed by Duncan in his comments, a DataSet structure has no point of being generic itself. 确实,正如Duncan在其评论中指出的那样,DataSet结构本身并不是通用的。 Still, some generics could still add some syntax sugar in attempt to avoid casting 尽管如此,某些泛型仍可能添加一些语法糖以尝试避免强制转换

If I am not mistaken ,your Hashtable contents variable hold the class of a Serializable Object as key and the Serializable Vector List as value 如果我没记错的话,您的Hashtable 内容变量会将Serializable Object的类作为键,将Serializable Vector List的值保留为值

   import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.io.Serializable;
    import java.util.Hashtable;
    import java.util.Vector;

    public class DataSet implements Serializable, PropertyChangeListener{

        Hashtable<Class,Vector<Serializable> contents = new Hashtable<Class,Vector<Serializable>();

        @Override
        public void propertyChange(PropertyChangeEvent arg0) {
            // TODO Auto-generated method stub

        }

        public void addObject(Serializable obj){

            Vector<Serializable> vector = contents.get(obj.getClass());
            if (vector == null){
                vector = new Vector<Serializable>();
                vector.add(obj);
                contents.put(obj.getClass(), vector);
              }
            else{
              vector.add(obj);
               }
        }

        public Vector<Serializable> getObjects(Class objType){
            if (contents.contains(objType)){
                return (Vector<Serializable>)contents.get(objType);
            }
            else{
                return new Vector<Serializable>();
            }
        }
    }

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

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