Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!gegeweb.org!de-l.enfer-du-nord.net!feeder2.enfer-du-nord.net!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: blmblm@myrealbox.com Newsgroups: comp.lang.java.programmer Subject: generics puzzle Date: 17 Oct 2011 10:41:08 GMT Organization: None Lines: 174 Message-ID: <9g2f24Fi0vU1@mid.individual.net> X-Trace: individual.net /3RXCB1YyQU3OpI/xZzO0gi31uTR/ubUdH56yKTl8vGKvgr3TK X-Orig-Path: not-for-mail Cancel-Lock: sha1:ZKD94dTKmnNzSL38n/EylfdPphk= X-Newsreader: trn 4.0-test76 (Apr 2, 2001) Xref: x330-a1.tempe.blueboxinc.net comp.lang.java.programmer:8904 I'm having a bit of trouble with generics, and while I've come up with ways of getting done what I want to get done, I wonder whether there's some nice solution that isn't occurring to me. The basic situation is this: I have an abstract generic class (call it GThing) with type parameter T, which has a method (call it set()) that takes a parameter of type T and another method (call it modified()) that returns a result of type T. I also have some classes that extend GThing and specify its type parameter, and code that is meant to operate on lists of instances of these various subclasses. What I would *like* to be able to do is construct a list of GThing objects and then do to each element of it something like the following: element.set(element.modified()) but the compiler objects to that, which I find reasonable enough, though I'm not enough of a generics expert to really articulate what the problem is. (I have a feeling that this "type erasure" thing, which I understand dimly at best, comes into it. :-)? ) One fix is to just introduce a method setFromModified() in GThing, but that doesn't appeal to me. An ugly-hack fix is to add to GThing a set() method that takes an Object and typecasts it, but -- yuck, right? In the same code I also have another generic class that "wraps" GThing (call it GThingWrapper), and a class that among other things contains a list of objects of the wrapper class (call it GThingWrapperList). One thing I want to do is add to that list of objects a new GThingWrapper constructed from a GThing, with the type parameter of the GThingWrapper matching the type parameter of the GThing. Initially that didn't work either, which also seems reasonable enough, *but* I discovered (by trial and error) a way to make it work using a generic method. Now I'm wondering whether somehow a generic method could be used to solve the first problem, but I'm not finding a way to do it. SSCCEs follow, one for the first situation (with a comment quoting the error message I get from Oracle's "javac" compiler, version 1.6.0_21 if that matters), and one for the second. I'd be glad of advice from anyone knowledgeable about generics and willing to wade through my code .... ==== SSCCE #1 ==== import java.util.ArrayList; import java.util.List; public class GenericsProblem { public static void main(String[] args) { List> things = new ArrayList>(); things.add(new IntegerThing(1)); things.add(new IntegerThing(2)); things.add(new StringThing("hello")); things.add(new StringThing("bye")); for (GThing t : things) { System.out.println(t.get()); } for (GThing t : things) { /* t.set(t.modified()); does not compile: set(capture#591 of ?) in GenericsProblem.GThing cannot be applied to (java.lang.Object) */ } for (GThing t : things) { /* ugly hack!? */ t.setG(t.modified()); } for (GThing t : things) { System.out.println(t.get()); } } public static abstract class GThing { private T val; protected GThing(T v) { val = v; } public T get() { return val; } public void set(T v) { val = v; } /* ugly hack!? */ @SuppressWarnings("unchecked") public void setG(Object v) { val = (T) v; } abstract T modified(); } public static class IntegerThing extends GThing { public IntegerThing(Integer i) { super(i); } @Override public Integer modified() { return get() * 2; } } public static class StringThing extends GThing { public StringThing(String s) { super(s); } @Override public String modified() { return get() + get(); } } } ==== SSCCE #2 ==== import java.util.ArrayList; import java.util.List; public class GenericsProblemSoln { public static void main(String[] args) { GThingWrapperList thingWrappers = new GThingWrapperList(); thingWrappers.add(new IntegerThing(1)); thingWrappers.add(new IntegerThing(2)); thingWrappers.add(new StringThing("hello")); thingWrappers.add(new StringThing("bye")); for (GThingWrapper tw : thingWrappers.elements()) { System.out.println(tw.getThing().get()); } for (GThingWrapper tw : thingWrappers.elements()) { tw.setModified(); } for (GThingWrapper tw : thingWrappers.elements()) { System.out.println(tw.getThing().get()); } } public static abstract class GThing { private T val; protected GThing(T v) { val = v; } public T get() { return val; } public void set(T v) { val = v; } abstract T modified(); } public static class IntegerThing extends GThing { public IntegerThing(Integer i) { super(i); } @Override public Integer modified() { return get() * 2; } } public static class StringThing extends GThing { public StringThing(String s) { super(s); } @Override public String modified() { return get() + get(); } } public static class GThingWrapper { private GThing thing; public GThingWrapper(GThing t) { thing = t; } public GThing getThing() { return thing; } public void setModified() { thing.set(thing.modified()); } } public static class GThingWrapperList { private List> thingWrappers = new ArrayList>(); public void add(GThing t) { thingWrappers.add(new GThingWrapper(t)); } public Iterable> elements() { return thingWrappers; } } } -- B. L. Massingill ObDisclaimer: I don't speak for my employers; they return the favor.