/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.lang.reflect.*;
import java.io.*;
class Ideone {
Builder[] registry = { new CircleBuilder()
, new SquareBuilder()
, new RectangleBuilder()
};
for (Builder<?> b : registry) b.shape().draw();
}
}
void draw();
}
public void draw
() { System.
out.
println("Rect"); } }
public void draw
() { System.
out.
println("Square"); } }
class Circle
implements Shape { public void draw
() { System.
out.
println("Circle"); } }
class Builder<SHAPE extends Shape> {
public final SHAPE shape = build();
@SuppressWarnings("unchecked")
private SHAPE build() {
try {
ParameterizedType parent =
(ParameterizedType) getClass().getGenericSuperclass();
Class<?> arg = (Class<?>) parent.getActualTypeArguments()[0];
return (SHAPE) arg.newInstance();
} catch (ReflectiveOperationException e) {
}
}
public SHAPE shape() { return shape; }
}
class CircleBuilder extends Builder<Circle> {}
class RectangleBuilder extends Builder<Rectangle> {}
class SquareBuilder extends Builder<Square> {}
LyogcGFja2FnZSB3aGF0ZXZlcjsgLy8gZG9uJ3QgcGxhY2UgcGFja2FnZSBuYW1lISAqLwoKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS5sYW5nLio7CmltcG9ydCBqYXZhLmxhbmcucmVmbGVjdC4qOwppbXBvcnQgamF2YS5pby4qOwoKY2xhc3MgSWRlb25lIHsKCXB1YmxpYyBzdGF0aWMgdm9pZCBtYWluIChTdHJpbmdbXSBhcmdzKSB0aHJvd3MgamF2YS5sYW5nLkV4Y2VwdGlvbiB7CgkJQnVpbGRlcltdIHJlZ2lzdHJ5ID0geyAgIG5ldyBDaXJjbGVCdWlsZGVyKCkKCQkgICAgICAgICAgICAgICAgICAgICAgICwgbmV3IFNxdWFyZUJ1aWxkZXIoKQoJCSAgICAgICAgICAgICAgICAgICAgICAgLCBuZXcgUmVjdGFuZ2xlQnVpbGRlcigpCgkJICAgICAgICAgICAgICAgICAgICAgICB9OwoJCSAgICAgICAgICAgICAgICAgICAgICAgCgkgICAgZm9yIChCdWlsZGVyPD8+IGIgOiByZWdpc3RyeSkgYi5zaGFwZSgpLmRyYXcoKTsKCX0KfQoKaW50ZXJmYWNlIFNoYXBlIHsKCXZvaWQgZHJhdygpOwp9CgpjbGFzcyBSZWN0YW5nbGUgaW1wbGVtZW50cyBTaGFwZSB7CglwdWJsaWMgdm9pZCBkcmF3KCkgeyBTeXN0ZW0ub3V0LnByaW50bG4oIlJlY3QiKTsgfQp9CgpjbGFzcyBTcXVhcmUgZXh0ZW5kcyBSZWN0YW5nbGUgewoJcHVibGljIHZvaWQgZHJhdygpIHsgU3lzdGVtLm91dC5wcmludGxuKCJTcXVhcmUiKTsgfQp9CgpjbGFzcyBDaXJjbGUgaW1wbGVtZW50cyBTaGFwZSB7CglwdWJsaWMgdm9pZCBkcmF3KCkgeyBTeXN0ZW0ub3V0LnByaW50bG4oIkNpcmNsZSIpOyB9Cn0KCmNsYXNzIEJ1aWxkZXI8U0hBUEUgZXh0ZW5kcyBTaGFwZT4gewoJCglwdWJsaWMgZmluYWwgU0hBUEUgc2hhcGUgPSBidWlsZCgpOwoJCglAU3VwcHJlc3NXYXJuaW5ncygidW5jaGVja2VkIikKCXByaXZhdGUgU0hBUEUgYnVpbGQoKSB7CgkJdHJ5IHsKCQkgICAgUGFyYW1ldGVyaXplZFR5cGUgcGFyZW50ID0KICAgICAgICAgICAgICAoUGFyYW1ldGVyaXplZFR5cGUpIGdldENsYXNzKCkuZ2V0R2VuZXJpY1N1cGVyY2xhc3MoKTsKICAgICAgICAgICAgQ2xhc3M8Pz4gYXJnID0gKENsYXNzPD8+KSBwYXJlbnQuZ2V0QWN0dWFsVHlwZUFyZ3VtZW50cygpWzBdOwogICAgICAgICAgICByZXR1cm4gKFNIQVBFKSBhcmcubmV3SW5zdGFuY2UoKTsKCQl9IGNhdGNoIChSZWZsZWN0aXZlT3BlcmF0aW9uRXhjZXB0aW9uIGUpIHsKCQkJdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oZSk7CgkJfQoJfQoJCglwdWJsaWMgU0hBUEUgc2hhcGUoKSB7IHJldHVybiBzaGFwZTsgfQp9CgpjbGFzcyBDaXJjbGVCdWlsZGVyIGV4dGVuZHMgQnVpbGRlcjxDaXJjbGU+IHt9CgpjbGFzcyBSZWN0YW5nbGVCdWlsZGVyIGV4dGVuZHMgQnVpbGRlcjxSZWN0YW5nbGU+IHt9CgpjbGFzcyBTcXVhcmVCdWlsZGVyIGV4dGVuZHMgQnVpbGRlcjxTcXVhcmU+IHt9