java - Using generics in non-static inner class -
public abstract class outerclass<ot extends outerclass<ot>> { public <c extends outerclass<?>> c parse(class<c> clazz) { if (clazz.isinstance(this)) { return (c) this; } return null; } public abstract class innerclass<ct extends innerclass<ct> { public <c extends innerclass<?>> c parse(class<c> clazz) { if (clazz.isinstance(this)) { return (c) this; } return null; } } } outerclass<?> oinstance; innerclass<?> iinstance;
in above example iinstance
variable works fine. iinstance
variable shows error when adding generics part
type arguments given on raw type
if remove generics part variables, below test cases fail type errors
public class extendedouter extends outerclass<extendedouter> { } // works on outerclass<?> , not on outerclass extendedouter einstance = oinstance.parse(extendedouter.class);
found: outerclass, required: extendedouter
this no problem on static/outer classes can defined classname<?>
, non-static inner classes cannot defined <?>
how can add <?>
iinstance
without making innerclass
static?
edit: let me give examples why these classes uses extended versions generic.
public abstract class outerclass<ot extends outerclass<ot>> { public abstract ot returnme(); } public class extendedouter extends outerclass<extendedouter> { @override public extendedouter returnme() { return this; } }
the above example not work if made return type outerclass
on abstract version. if so, extended versions have casted whenever method used, not seam ideal.
also got error androidstudio after removing <ct>
in <t extends outerclass<ct>>
the parameter ot not within it's bound
this error shown in extended classes when doing classname extends outerclass<classname>
. in other words not work using <t extends outerclass>
on abstract classes.
similar previous post did showcased builder patter uses generic types , inheritance reduce actual code in inheritance cases, possible none-static classes. therefore modified builder example accordingly avoid static inner-classes:
parent class parent builder:
public abstract class testparam<z> { public abstract class commonbuilder<t extends commonbuilder<t>> { protected final string a; protected final string b; protected final string c; protected z z = null; public commonbuilder(string a, string b, string c) { this.a = a; this.b = b; this.c = c; } @suppresswarnings("unchecked") public t withoptionalz(z z) { this.z = z; return (t)this; } @suppresswarnings("hiding") public abstract <t> t build(); } protected string name; protected string a; protected string b; protected string c; protected z z = null; protected testparam() { } protected testparam(string name, string a, string b, string c) { this.name = name; this.a = a; this.b = b; this.c = c; } protected testparam(string name, string a, string b, string c, z z) { this.name = name; this.a = a; this.b = b; this.c = c; this.z = z; } public string geta() { return a; } public string getb() { return b; } public string getc() { return c; } protected abstract string getcontent(); @override public string tostring() { return name+"[a: " + + ", b: " + b + ", c: " + c + (z != null ? ", z: " + z.tostring() : "") + getcontent() +"]"; } }
a child class none-static builder looks this:
@suppresswarnings({"hiding", "unchecked"}) public class testparama<d,e,z> extends testparam<z> { public class builder<t extends testparama<d,e,z>, b extends testparama<d,e,z>.builder<? extends testparama<d,e,z>, ? extends b, d, e>, d,e> extends testparam<z>.commonbuilder<builder<testparama<d,e,z>,b, d,e>> { protected d d; protected e e; public builder(string a, string b, string c) { super(a, b, c); } public b withd(d d) { this.d = d; return (b)this; } public b withe(e e) { this.e = e; return (b)this; } @override public <t> t build() { testparama<d,e,z> t = new testparama<>("testparama", a, b, c, z, d, e); return (t)t; } } protected d d; protected e e; public testparama() { super(); } protected testparama(string name, string a, string b, string c, z z, d d, e e) { super(name, a, b, c, z); this.d = d; this.e = e; } public d getd() { return d; } public e gete() { return e; } @override protected string getcontent() { return ", d: " + d + ", e: " + e; } }
to test functionality of outer/inner classes can implement this:
public class main { public static void main(string ... args) { testparama<d,e,string> = new testparama<>().new builder<>("a","b","c").withd(new d()).withe(new e()).build(); testparamb<f,g,string> b = new testparamb<>().new builder<>("a","b","c").withf(new f()).withg(new g()).withoptionalz("z").build(); testparam<string> c = new testparama<>().new builder<>("a","b","c").withd(new d()).withe(new e()).withoptionalz("z").build(); testparam<?> d = new testparamb<>().new builder<>("a","b","c").withf(new f()).withg(new g()).build(); test(a); test(b); test(c); test(d); testparam<?>.commonbuilder<? extends testparam<?>.commonbuilder<?>> builder = new testparama<>().new builder<>("a", "b", "c").withd(new d()).withe(new e()); test(builder); // or bit shorter testparam<?>.commonbuilder<?> builder2 = new testparamb<>().new builder<>("a", "b", "c").withf(new f()).withg(new g()); test(builder2); } public static void test(testparama<?,?,?> testparam) { system.out.println("test parama: " + testparam.tostring()); } public static void test(testparamb<?,?,?> testparam) { system.out.println("test paramb: " + testparam.tostring()); } public static void test(testparam<?> testparam) { system.out.println("test param: " + testparam.tostring()); } public static void test(testparam<?>.commonbuilder<?> builder) { system.out.println("test commonbuilder: " + builder.build().tostring()); } }
testparamb
identical testparama
- contains varialbe , builder-methods f
, g
instead of d
, e
. furthermore, d
, e
, f
, g
classes simple tostring()
implementation returns simple classname.
this print following output:
test parama: testparama[a: a, b: b, c: c, d: d, e: e] test paramb: testparamb[a: a, b: b, c: c, z: z, f: f, g: g] test param: testparama[a: a, b: b, c: c, z: z, d: d, e: e] test param: testparamb[a: a, b: b, c: c, f: f, g: g] test commonbuilder: testparama[a: a, b: b, c: c, d: d, e: e] test commonbuilder: testparamb[a: a, b: b, c: c, f: f, g: g]
Comments
Post a Comment