简体   繁体   中英

Automatic type casting

I have a program that needs to accept objects of which the class types are only known at runtime. I was wondering if it's possible to have the program automatically cast back the objects to the correct class type?

The following code is what I currently have; I will explain what I expect it to do step-by-step:

  1. Create a TryingSomething instance that adds two sets (one of class type Foo , one of class type Bar ).
  2. The sets are supposed to be added to the hashmap. At this point I already get a warning from Eclipse, warning me that the sets are not compatible somehow. The types are the same though. What went wrong here?
  3. Moving on, assuming the previous step did work as intended. I wish to retrieve the collections in the main method again, but already cast to the correct class types ( Foo and Bar ). Will this work? If not, is there an alternative that allows me to retrieve the objects back in their correct class type?
  4. (Bonus) The name String that's attached with each collection, is introduced to allow me to distinguish between the different class types. It would be even better if it was possible to achieve the results in step 3, without needing the String.

Thanks to anyone who can give me some pointers.

class TryingSomething<T> {
    private Map<String, Set<T>> map = new HashMap<String, Set<T>>();

    public void addCollection(Set<T> s, String name){
        this.map.put(name, s);
    }

    public void test(){
        Set<Foo> foo = new HashSet<Foo>();
        Set<Bar> bar = new HashSet<Bar>();
        addCollection(foo, "foo");
        addCollection(bar, "bar");
    }

    public Set<T> getCollections(String name){
        return this.map.get(name);
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args){
        TryingSomething t = new TryingSomething();
        Set<Foo> foo = new HashSet<Foo>();
        Set<Bar> bar = new HashSet<Bar>();
        t.addCollection(foo, "foo");
        t.addCollection(bar, "bar");
        Set<Foo> fooList = t.getCollections("foo");
        Set<Bar> barList = t.getCollections("bar");
    }

}

class Foo{
}

class Bar{
}

You can use the class objects (runtime types) of the classes for your map keys:

class TryingSomething {
    private Map<Class<?>, Set<?>> map = new HashMap<>();

    public <T> void addCollection(Set<T> s, Class<T> clazz){
        map.put(clazz, s);
    }

    public void test(){
        Set<Foo> foo = new HashSet<Foo>();
        Set<Bar> bar = new HashSet<Bar>();
        addCollection(foo, Foo.class);
        addCollection(bar, Bar.class);
    }

    @SuppressWarnings("unchecked")
    public <T> Set<T> getCollections(Class<T> clazz){
        return (Set<T>)this.map.get(clazz);
    }


    public static void main(String[] args){
        TryingSomething t = new TryingSomething();
        Set<Foo> foo = new HashSet<Foo>();
        Set<Bar> bar = new HashSet<Bar>();
        t.addCollection(foo, Foo.class);
        t.addCollection(bar, Bar.class);
        Set<Foo> fooList = t.getCollections(Foo.class);
        Set<Bar> barList = t.getCollections(Bar.class);
    }

}

class Foo{
}

class Bar{
}

The class TryingSomething shouldn't be generic because you want to store sets of arbitrary types (chosen dynamically at runtime). Note that this implementation does not check if an inserted set actually contains objects of the specified type at all (neither at insertion nor at retrieval) - the reponsibility here lies with the user of this container class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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