Powered by: newtelligence dasBlog 1.9.7067.0
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2008 , Ted Neward
E-mail
So an attendee comes up to me at one of the past NFJS shows, with this challenge:
The implementation does not know what parametrized Iterable class will be used. The Iterable class will need to know what class it contains. Interfaces are passed to the factory and it calls a lookup to identify (or create) the implementing class. Can this be done without causing a compile warning? // usage: Seq<Item> items = factory.createBean(null, Seq.class, Item.class); // interface: public abstract <T> T getBean(String localName, Class<T> javaClass, Type... typeArguments); // impl: public <T> T createBean(String localName, Class<T> javaClass, Type... typeArguments) { Resource resource = createResource(localName); Collection<STRING> rdfTypes = findRdfTypes(javaClass); for (String rdfType : rdfTypes) { addStatement(resource, RDF.TYPE, createResource(rdfType)); } T bean = rdfBeanFactory.createBean(this, resource, rdfTypes, javaClass); if (typeArguments != null && bean instanceof RdfParameterizedBean) ((RdfParameterizedBean)bean).setActualTypeArguments(typeArguments); return bean; } -- Some ideas I have tried. import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.Set; public class test { public static class plain { public static Collection getSomethingOf(Class type, Class contentType) throws Exception { Collection result = (Collection) type.newInstance(); // cast result.addAll(Arrays.asList(contentType.newInstance())); // warning return result; } public static Set<Date> getSetOfDate() throws Exception { return (Set<Date>) getSomethingOf(HashSet.class, Date.class); // warning } } public static class fixed { public static <C> Collection<C> getSomethingOf(Class<? extends Collection> type, Class<C> contentType) throws Exception { Collection<C> result = type.newInstance(); // warning result.addAll(Arrays.asList(contentType.newInstance())); return result; } public static Set<Date> getSetOfDate() throws Exception { return (Set<Date>) getSomethingOf(HashSet.class, Date.class); // cast } } public static class external { public static <C, Collection<C extends T>> T getSomethingOf2(Class<T> type, Class<C> contentType) throws Exception { T result = type.newInstance(); result.addAll(Arrays.asList(contentType.newInstance())); return result; } public static Set<Date> getSetOfDate2() throws Exception { Class<HashSet<Date>> type = (Class<HahSet>) HashSet.class; // warning return getSomethingOf2(type, Date.class); } } public static class internal { public static <C, T extends Collection, R extends Collection<C>> R getSomethingOf(Class<T> type, Class<C> contentType) throws Exception { R result = (R) type.newInstance(); // warning result.addAll(Arrays.asList(contentType.newInstance())); return result; } public static Set<Date> getSetOfDate() throws Exception { return getSomethingOf(HashSet.class, Date.class); } }
// usage: Seq<Item> items = factory.createBean(null, Seq.class, Item.class); // interface: public abstract <T> T getBean(String localName, Class<T> javaClass, Type... typeArguments); // impl: public <T> T createBean(String localName, Class<T> javaClass, Type... typeArguments) { Resource resource = createResource(localName); Collection<STRING> rdfTypes = findRdfTypes(javaClass); for (String rdfType : rdfTypes) { addStatement(resource, RDF.TYPE, createResource(rdfType)); } T bean = rdfBeanFactory.createBean(this, resource, rdfTypes, javaClass); if (typeArguments != null && bean instanceof RdfParameterizedBean) ((RdfParameterizedBean)bean).setActualTypeArguments(typeArguments); return bean; } -- Some ideas I have tried. import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.Set; public class test { public static class plain { public static Collection getSomethingOf(Class type, Class contentType) throws Exception { Collection result = (Collection) type.newInstance(); // cast result.addAll(Arrays.asList(contentType.newInstance())); // warning return result; } public static Set<Date> getSetOfDate() throws Exception { return (Set<Date>) getSomethingOf(HashSet.class, Date.class); // warning } } public static class fixed { public static <C> Collection<C> getSomethingOf(Class<? extends Collection> type, Class<C> contentType) throws Exception { Collection<C> result = type.newInstance(); // warning result.addAll(Arrays.asList(contentType.newInstance())); return result; } public static Set<Date> getSetOfDate() throws Exception { return (Set<Date>) getSomethingOf(HashSet.class, Date.class); // cast } } public static class external { public static <C, Collection<C extends T>> T getSomethingOf2(Class<T> type, Class<C> contentType) throws Exception { T result = type.newInstance(); result.addAll(Arrays.asList(contentType.newInstance())); return result; } public static Set<Date> getSetOfDate2() throws Exception { Class<HashSet<Date>> type = (Class<HahSet>) HashSet.class; // warning return getSomethingOf2(type, Date.class); } } public static class internal { public static <C, T extends Collection, R extends Collection<C>> R getSomethingOf(Class<T> type, Class<C> contentType) throws Exception { R result = (R) type.newInstance(); // warning result.addAll(Arrays.asList(contentType.newInstance())); return result; } public static Set<Date> getSetOfDate() throws Exception { return getSomethingOf(HashSet.class, Date.class); } }
If I'm feeling bored one day I'll try coding it in C#, just to (hopefully) exemplify the differences in the generics model between the two.
UPDATE: Hopefully I got the formatting right this time; have I mentioned how much I hate the fact that Java, C# and C++ all use the left-pointy-bracket/right-pointy-bracket syntax when posting code snippets like this...?