I want to do something like this:
public class Parent {
private static final Map<Class<?>, Object> map;
static {
map = new IdentityHashMap<>();
}
public Parent() {
if (map.get(getKey()) == null) {
map.put(getKey(), new Object());
}
}
private static Class<?> getKey() {
return /*something*/;
}
public static Object getValue() {
return map.get(getKey());
}
}
public class Child extends Parent {
}
Child.getValue() // returns an object
Parent.getValue() // returns other object
I tried to use MethodHandles.lookup().lookupClass() in getKey(), but it returns Parent class when calling Child.getValue() (eg:
public class Parent {
private static final Map<Class<?>, Object> map;
static {
map = new IdentityHashMap<>();
}
public Parent() {
if (map.get(getKey()) == null) {
map.put(getKey(), new Object());
}
}
private static Class<?> getKey() {
Class<?> clazz = MethodHandles.lookup().lookupClass();
System.out.println(clazz.getName());
return clazz;
}
public static Object getValue() {
return map.get(getKey());
}
}
public class Child extends Parent {
}
Child.getValue()
// console output: my.project.package.Parent
// i want: my.project.package.Child
)
How i can do this? I tried to use all cases from this: Getting the class name from a static method in Java, and in every case it prints in console parent class name.
UPD: the getValue() method should be static, i can't do anything with it.
UPD2: I know that such code is bad practice, and I know why this problem arises, but I did not write the getValue() method and it does not depend on me, and I want to find out any way to perform the task described in the question, even using reflection, the MethodHandles or something else
Related
I want my method "themethod" is referencing "foo", then in a static block, try to get the method "foo" with "getMethod", to which I pass the name of the method and type of the parameters, but "foo "receives as a parameter a type generic, then I know not to give to work.
Code:
public class Clazz<T>
{
static Method theMethod;
static
{
try
{
Class<Clazz> c = Clazz.class;
theMethod = c.getMethod( "foo", T.class ); // "T.class" Don't work!
}
catch ( Exception e )
{
}
}
public static <T> void foo ( T element )
{
// do something
}
}
How do I make "theMethod" referencing a method called 'foo'?
Something like this?
import java.lang.reflect.Method
public class Clazz<T>
{
static Method theMethod;
static Class<T> type;
public Clazz(Class<T> type) {
this.type = type;
this.theMethod = type.getMethod("toString");
}
}
System.out.println(new Clazz(String.class).theMethod);
Gives
public java.lang.String java.lang.String.toString()
This should work in the most cases:
public class Clazz<T> {
static Method theMethod;
static {
try {
Class<Clazz> c = Clazz.class;
theMethod = c.getDeclaredMethod("foo", Object.class);
} catch(Exception e) {}
}
public static <T> void foo(T element) {
// do whatever
}
}
I need some help on the below post as I am not able to get the derived object out of base object using generics and I wish not to use the downcasting.
Java Abstract Classes: Returning "this" pointer for derived classes
I am very much interested in seeing the code example set up by #Adam Arold in the post.
public <T extends KeyException> T withId(final String Id) {
this.Id = Id;
return (T)this;
}
I cannot comment on that post as I need rep points to do that, so I am posting new one.
I essentially tried this and I get some warnings,
public class KeyException <T extends KeyException<T>> {
private static final long serialVersionUID = 1L;
protected String Id;
public String getId() {
return Id;
}
// The type parameter T is hiding the type T
public <T extends KeyException<T>> T withId(final String Id) {
this.Id = Id;
return (T)this; //Type safety: Unchecked cast from KeyException<T> to T
}
}
What would be the correct way to use generics to avoid downcasting ?
My code below,
class Foo<TSelf extends Foo<?>> {
Class<TSelf> selfClass;
Foo(Class<TSelf> selfClass) {
if (!this.getClass().equals(selfClass))
throw new IllegalArgumentException();
this.selfClass = selfClass;
}
TSelf returnThis() {
return selfClass.cast(this);
}
}
class Bar extends Foo<Bar> {
Bar() {
super(Bar.class);
}
public int id = 10;
public static void main(String str[]) {
Bar b = new Bar();
b.id = 10;
Foo F = new Bar();
F.returnThis().id = 20; // Error, id cannot be resolved or is not a field
}
}
Implementation of builder pattern with "Fluent" interface,
// Base Class here
public abstract class Foo {
protected final String className;
protected Foo(Builder<?> builder) {
this.className = builder.className;
}
/* Builder class */
public static abstract class Builder<T extends Builder<?>> {
Class<T> selfClass;
protected String className;
public Builder(Class<T> selfClass) {
if (!this.getClass().equals(selfClass))
throw new IllegalArgumentException();
this.selfClass = selfClass;
}
public Builder<?> withClassName(String className) {
this.className = className;
return self();
}
public T self() {
return selfClass.cast(this);
}
/* build the Option */
public abstract Foo build();
private void validate() {
if(className != null)
throw new IllegalArgumentException();
}
}
}
// Derived Class here
public class Bar extends Foo {
private final String barProp;
private Bar(Builder builder) {
super(builder);
this.barProp = builder.barProp;
}
/* Builder class */
public static class Builder extends Foo.Builder<Bar.Builder> {
private String barProp = null;
public Builder() {
super(Bar.Builder.class);
}
public Bar.Builder withBarProp(String barProp) {
this.barProp = barProp;
return self();
}
public Bar build() {
if(barProp != null)
throw new IllegalArgumentException();
return new Bar(this);
}
}
public static void main(String[] args) {
Foo f1 = new Bar.Builder()
.withBarProp("Prop 1")
.withClassName("Bar") // works fine
.build();
Foo f2 = new Bar.Builder()
.withClassName("Bar")
.withBarProp("Prop 1") // does not work
.build();
}
}
You're shadowing the T parameter in withId(). This means that the T used in the method is different than T used in the class scope. Just use:
public T withId(String id) {
...
}
That said, what you're trying to do probably can't be made type-safe. KeyException simply cannot guarantee that the type of this is T. The type system cannot express that constraint and I have a hunch that it can't even be made to do so, as in it would cause more trouble than it solves.
The closest you can get to is the still boilerplatey workaround that only works for one level of inheritance:
class Foo<TSelf extends Foo> {
Class<TSelf> selfClass;
Foo(Class<TSelf> selfClass) {
if (!this.getClass().equals(selfClass))
throw new IllegalArgumentException();
this.selfClass = selfClass;
}
TSelf returnThis() {
return selfClass.cast(this);
}
}
class Bar extends Foo<Baz> {
Bar() {
super(Baz.class);
}
}
This still requires you to spell out what type you want your withId() etc... methods to return, but at least you don't have to override each and every one of them.
To avoid the downcast you can pull the withId method which needs to return the self-type into an interface. The abstract class can then implement the interface with a self-type of itself. That then allows it to avoid the downcast. Any subclasses of the abstract class can safely return this using return type covariance.
This avoids the downcast but it means that subclasses of the abstract class aren't typed with a self-type, which may be a problem depending on your use cases.
public interface IFace<SELF extends IFace<SELF>> {
SELF withId(String id);
}
abstract class Type1 implements IFace<Type1> {
#Override
public Type1 withId(String id) {
return this;
}
}
class Type2 extends Type1 {
#Override
public Type2 withId(String id) {
return this;
}
}
I've created two enum classes as singleton:
public enum A {
INSTANCE;
public void init(param p1, param p2) {
}
public void connect() {
}
public void disconnect() {
}
public bool isConnected() {
}
}
public enum B {
INSTANCE;
public void init(param p1) {
}
public void connect() {
}
public void disconnect() {
}
public bool isConnected() {
}
}
As you can see both enum classes are very similar so I was wondering if I should create some kind of base abstract class/enum or interface and then have these two enums extend or implement from it.
UPDATE 1: I'd like to put some shared member variables on the base class
UPDATE 2: Should I just change the way I'm defining the singleton?
As per java enum tutorial
All enums implicitly extend java.lang.Enum. Since Java does not
support multiple inheritance, an enum cannot extend anything else.
Here is interesting SO discussion related to this topic.
As Nambari stated you can't have an enum extend anything. However what they neglected to say is you CAN have an enum implement an interface, which is done as with a class using the implements keyword. I've done this at work and it's very useful in the right situation! There's an example here: http://javahowto.blogspot.co.uk/2008/04/java-enum-examples.html
There is a sweet little class called a DynamicObjectAdapterFactory posted by Heinz Kabutz which uses generics and reflection to adapt an object to implement an interface by providing it with a source class that already implements the interface.
Using it like below you can wrap your INSTANCE in a proxy. Of course the resulting object is no longer an enum but it does retain all of the singletonness of the enum I think. It also, obviously - can use any object to implement your interface.
I think this is as close as you will get to an enum extending a class.
Here's some test code that seems to work. Obviously the object is no longer an enum but as your aim was a singleton this may be acceptable.
public class Test {
// To implement this.
public interface Implement {
public void init();
public void connect();
public void disconnect();
public boolean isConnected();
}
// An implementor that does implement.
public static class Implements implements Implement {
#Override
public void init() {
}
#Override
public void connect() {
}
#Override
public void disconnect() {
}
#Override
public boolean isConnected() {
return false;
}
}
// Extend the INSTANCE in this.
public enum Extend {
INSTANCE;
// Hold my adapted version - thus still a singleton.
public final Implement adaptedInstance;
Extend () {
// Use the constructor to adapt the instance.
adaptedInstance = DynamicObjectAdapterFactory.adapt(this, Implement.class, new Implements());
}
}
// Provides an INSTANCE that has been extended by an Implements to implement Implement.
public static Implement getInstance () {
return Extend.INSTANCE.adaptedInstance;
}
public void test() {
System.out.println("Hello");
Implement i = getInstance();
}
public static void main(String args[]) {
new Test().test();
}
}
Here's the DynamicObjectAdapterFactory - I've tweaked it a little from the original - I hope Dr. Kabutz does not object.
public class DynamicObjectAdapterFactory {
// Use methods in adaptee unless they exist in target in which case use adapter.
// Implement target in passing.
public static <T> T adapt(final Object adaptee,
final Class<T> target,
final Object adapter) {
return (T) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{target},
new InvocationHandler() {
private final String name =
adaptee.getClass().getSimpleName() + "(" + adaptee.toString() + ")"
+ "+" + adapter.getClass().getSimpleName() + "(" + adapter.toString() + ")";
// The methods I wish to adapt.
private Map<MethodIdentifier, Method> adaptedMethods = new HashMap<>();
{
// initializer block - find all methods in adapter object
Method[] methods = adapter.getClass().getDeclaredMethods();
for (Method m : methods) {
// Keep a map of them.
adaptedMethods.put(new MethodIdentifier(m), m);
}
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// Has it been adapted?
Method otherMethod = adaptedMethods.get(new MethodIdentifier(method));
if (otherMethod != null) {
return otherMethod.invoke(adapter, args);
} else {
return method.invoke(adaptee, args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
#Override
public String toString() {
StringBuilder s = new StringBuilder();
// Really simple. May get more flexible later.
s.append("Adapted: ").append(name);
return s.toString();
}
});
}
private static class MethodIdentifier {
private final String name;
private final Class[] parameters;
public MethodIdentifier(Method m) {
name = m.getName();
parameters = m.getParameterTypes();
}
#Override
public boolean equals(Object o) {
// I am always equal to me.
if (this == o) {
return true;
}
// I cannot be equal to something of a different type.
if (!(o instanceof MethodIdentifier)) {
return false;
}
MethodIdentifier mid = (MethodIdentifier) o;
return name.equals(mid.name) && Arrays.equals(parameters, mid.parameters);
}
#Override
public int hashCode() {
return name.hashCode();
}
}
}
You can use the abstract class below for singleton instead of enum.
public abstract class AbstractSingleton {
private static Map<String, AbstractSingleton> registryMap = new HashMap<String, AbstractSingleton>();
AbstractSingleton() throws SingletonException {
String clazzName = this.getClass().getName();
if (registryMap.containsKey(clazzName)) {
throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!");
} else {
synchronized (registryMap) {
if (registryMap.containsKey(clazzName)) {
throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!");
} else {
registryMap.put(clazzName, this);
}
}
}
}
#SuppressWarnings("unchecked")
public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz) throws InstantiationException, IllegalAccessException {
String clazzName = clazz.getName();
if (!registryMap.containsKey(clazzName)) {
synchronized (registryMap) {
if (!registryMap.containsKey(clazzName)) {
T instance = clazz.newInstance();
return instance;
}
}
}
return (T) registryMap.get(clazzName);
}
public static AbstractSingleton getInstance(final String clazzName)
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
if (!registryMap.containsKey(clazzName)) {
Class<? extends AbstractSingleton> clazz = Class.forName(clazzName).asSubclass(AbstractSingleton.class);
synchronized (registryMap) {
if (!registryMap.containsKey(clazzName)) {
AbstractSingleton instance = clazz.newInstance();
return instance;
}
}
}
return registryMap.get(clazzName);
}
#SuppressWarnings("unchecked")
public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz, Class<?>[] parameterTypes, Object[] initargs)
throws SecurityException, NoSuchMethodException, IllegalArgumentException,
InvocationTargetException, InstantiationException, IllegalAccessException {
String clazzName = clazz.getName();
if (!registryMap.containsKey(clazzName)) {
synchronized (registryMap) {
if (!registryMap.containsKey(clazzName)) {
Constructor<T> constructor = clazz.getConstructor(parameterTypes);
T instance = constructor.newInstance(initargs);
return instance;
}
}
}
return (T) registryMap.get(clazzName);
}
static class SingletonException extends Exception {
private static final long serialVersionUID = -8633183690442262445L;
private SingletonException(String message) {
super(message);
}
}
}
From: https://www.cnblogs.com/wang9192/p/3975748.html
I have a class in which i have intialized hashmap in static block. Passing the key, I have retrived the value which is a class. In order to create object for this class. I have used the constructor class to get the constructor and passed arguments and created object.
I have two class in hashmap. To create objectfor EchoExpression I need to pass two arguments and for OutExpression class i need to pass only one argument(String).
Question:
Based on the class returned by the key I need to execute which constructor to get and implement, whether the constructor with one argument or two argument.
public class ExampleFactory {
private static HashMap<String,Class<?>> hmap = new HashMap<String,Class<?>>();
static
{
hmap.put("echo", EchoExpression.class);
hmap.put("Out", OutExpression.class);
}
public void getExpo(String key,String expression)
{
Class aClass =map.get(key);
//Constructor implementation for OutExpression where only one argument string is passed
Constructor constructor = aClass.getConstructor(new Class[]{String.class});
Object object= constructor.newInstance(expression);
//constructor for passing two arguments string for EchoExpression
Constructor constructor = aClass.getConstructor(new Class[]{String.class,Class.class});
Object object= constructor.newInstance(expression, Boolean.class);
return null;
}
}
How to choose from the value(class) which class to implement without using if else?
Use an Enum and switch on it. Here is a executable stub without getting too deeply into the reflection or the syntax of your example:
package com.trip.test;
import java.util.HashMap;
import java.util.Map;
public class ExampleFactory {
private static Map<String, Class<?>> hmap = new HashMap<String, Class<?>>();
static {
hmap.put("echo", EchoExpression.class);
hmap.put("Out", OutExpression.class);
}
public static void getExpo(String key, String expression) {
Class aClass = hmap.get(key);
ClassMappingEnum myType = ClassMappingEnum.getClassMappingEnum(aClass);
switch (myType) {
case ECHO_EXPRESSION:{
System.out.println(aClass.getName());
// do something
break;
}
case OUT_EXPRESSION:{
System.out.println(aClass.getName());
// do something
break;
}
case UNKNOWN:
default:
System.out.println("Bummer: " + aClass.getName());
}
}
public static void main(String[] args) {
getExpo("echo", "B");
getExpo("Out", "B");
}
}
enum ClassMappingEnum {
ECHO_EXPRESSION(EchoExpression.class), OUT_EXPRESSION(OutExpression.class), UNKNOWN(null);
private Class typeDes;
private ClassMappingEnum(Class typeDes) {
this.typeDes = typeDes;
}
public static ClassMappingEnum getClassMappingEnum(Class compare) {
for (ClassMappingEnum cme : ClassMappingEnum.values()) {
if (cme.typeDes.equals(compare)) {
return cme;
}
}
return UNKNOWN;
}
}
class EchoExpression<T> {
private String someString;
private Class<T> someClass;
public EchoExpression(String someString, Class<T> someClass) {
super();
this.someString = someString;
this.someClass = someClass;
}
public String getSomeString() {
return someString;
}
public void setSomeString(String someString) {
this.someString = someString;
}
public Class<T> getSomeClass() {
return someClass;
}
public void setSomeClass(Class<T> someClass) {
this.someClass = someClass;
}
}
class OutExpression {
private String someString;
public OutExpression(String someString) {
super();
this.someString = someString;
}
public String getSomeString() {
return someString;
}
public void setSomeString(String someString) {
this.someString = someString;
}
}
If you can modify the classes so both constructor has the same signature (accepts the same number/type of arguments in the same order), you could do
Constructor constructor = aClass.getConstructor(new Class[]{String.class,Class.class});
Object object= constructor.newInstance(expression, Boolean.class);
for both classes.
This of course means that the class that right now do not need the extra parameter, will have to ignore the passed-in one it was not using before after the change
UPDATE: Here is a possible way of implementing the idea using Factory classes:
public interface ObjectFactory
{
Object create(String expr, Class cls);
}
public class EchoExpressionFactory implements ObjectFactory
{
public EchoExpression create(String expr, Class cls)
{
return new EchoExpression(expr, cls);
}
}
public class OutExpressionFactory implements ObjectFactory
{
public OutExpression create(String expr, Class cls)
{
return new OutExpression(expr);
}
}
public class ExampleFactory {
private static HashMap<String,ObjectFactory> hmap = new HashMap<String,ObjectFactory>();
static
{
hmap.put("echo", new EchoExpressionFactory());
hmap.put("Out", new OutExpressionFactory());
}
public void getExpo(String key,String expression)
{
ObjectFactory factory = map.get(key);
//Constructor implementation for Expression
Object object = factory.create(expression);
Object object= constructor.newInstance(expression, Boolean.class);
return;
}
}
I have first class for which constructor takes a parameter.
public class First {
First(Object o){
o.toString();
}
}
I have a second class which extends this first one.
public class Second extends First {
Second(Object o) {
super(o);
}
}
What I want is to keep the constructor of Second class private in order to have a possibility to instantiate the only one instance of this class (using Singleton pattern, for instance), but compiler doesn't allow me to do that.
If I can't set the constructor as private here, what can I do to allow the only one instance of the class to be created?
You can make the constructor of Second private with no problems. What you can't do is make the constructor of First private, unless you use nested classes.
As an example, this works fine:
class First {
First(Object o) {
o.toString();
}
}
class Second extends First {
private final static Second instance = new Second(new Object());
private Second(Object o) {
super(o);
}
public static Second getInstance() {
return instance;
}
}
Here it is working !!
class First {
First(Object o){
o.toString();
}
public First() {//I think you missed this
}
}
class Second extends First {
private static Second obj ;
private Second(Object o) {
super(o);
}
private Second() {
}
public static Second getInstance(){
if(obj == null){
obj = new Second(new Object());
}
return obj;
}
}
public class SingleTon {
public static void main(String[] args) {
Second sObj = Second.getInstance();
}
}
public class Second extends First{
private static final Second instance = new Second(new Object());
private Second(Object o) {
super(o);
}
public static Second instance(){
return instance;
}
}