Condition to choose which getConstructor method - java

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;
}
}

Related

How to get Class<?> from static method?

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

Downcast reference to runtime-known class

Is there any way by which I can cast a reference of type Object, assuming that the reference could point to any class I defined, to said defined class at runtime?
I've been trying to work it out and the code I came out with is:
public class SomeTestBench {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
myEntity a = new myEntity("Hello Code!");
Receptacle cage = new Receptacle();
cage.injectYourEntity(a);
((cage.itsClass) cage.theEntity).exertExistence();
}
}
That unfortunately does not work, as the class argument to that cast must be static.
Rest of the code:
public class myEntity extends Object{
String warcry;
myEntity(String warcry){
this.warcry = warcry;
}
public void exertExistence(){
System.out.println(this.warcry);
}
}
public class Receptacle {
Object theEntity;
Class itsClass;
public void injectYourEntity(Object it){
this.theEntity = it;
this.itsClass = it.getClass();
}
public void prodIt(){
System.out.println(theEntity.getClass());
}
}
Why don't you just do this using Generics.
public static void main(String[] args) {
myEntity a = new myEntity("Hello Code!");
Receptacle<myEntity> cage = new Receptacle<>();
cage.injectYourEntity(a);
cage.theEntity.exertExistence();
}
//
//That unfortunately does not work, as the class argument to that cast must be static.
//
//Rest of the code:
class myEntity {
String warcry;
myEntity(String warcry){
this.warcry = warcry;
}
public void exertExistence(){
System.out.println(this.warcry);
}
}
class Receptacle<T> {
T theEntity;
public void injectYourEntity(T it){
this.theEntity = it;
}
public void prodIt(){
System.out.println(theEntity.getClass());
}
}
To call a no-arg method named exertExistence() on an object of unknown type, you have three choices:
Use generics. See answer by WJS.
Use reflection:
Receptacle cage = new Receptacle();
cage.injectYourEntity(new myEntity("Hello Code!"));
Method method = cage.itsClass.getMethod("exertExistence", null);
method.invoke(cage.theEntity, null);
Use an interface (recommended):
Receptacle cage = new Receptacle();
cage.injectYourEntity(new myEntity("Hello Code!"));
cage.theEntity.exertExistence();
interface MyInterface {
void exertExistence();
}
class myEntity implements MyInterface {
String warcry;
myEntity(String warcry){
this.warcry = warcry;
}
#Override
public void exertExistence(){
System.out.println(this.warcry);
}
}
class Receptacle {
MyInterface theEntity;
public void injectYourEntity(MyInterface it){
this.theEntity = it;
}
}

Java Abstract Classes: Returning “this” pointer for derived classes "follow up"

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;
}
}

java - Abstract base enum/class for singleton

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

How to identify the returned object's type of a method?

I have a helper class which gets notified by the below method
public void setObject(Object obj) {
this.obj = obj
}
There is getter method for the obj. Is there any way to identify the caller about the type of the obj. The object can take any object like :
List<Switch>
Switch
List<Link>
The caller has to process the obj after calling the getter method. Is there a way to do it?
You can always know the class (and then the class name) from obj.getClass(). What you want to do with it further ?
If you want to invoke methods on the obj - You need reflection..
Something like this -
Class myClass = obj.getClass();
Method m = myClass.getDeclaredMethod("get",new Class[] {});
Object result = m.invoke(myObject,null);
You could know the object type using instanceof operator.Consider the following example:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
if (getObject() instanceof A) {
System.out.println("A class");
}
if (getObject() instanceof B) {
System.out.println("B class");
}
if (getObject() instanceof List) {
System.out.println("List class");
}
}
/**
*
* #return Object type.
*/
public static Object getObject() {
//Change this value to new A() or new B();
return new ArrayList<A>();
}
}
class A {
private String aName;
public A(String aName) {
this.aName = aName;
}
public String getaName() {
return aName;
}
public void setaName(String aName) {
this.aName = aName;
}
}
class B {
private String bName;
public B(String bName) {
this.bName = bName;
}
public String getbName() {
return bName;
}
public void setbName(String bName) {
this.bName = bName;
}
}
As you can see I have a method returning object type and if you are gonna change the returning value of that method you can easily understand what is going on.And one more thing you can't guess the generic types at runtime because "Generic types are erased before runtime".Hope you got my point.Cheers
This might help you. It informs you how to get the parameterized type.
Get generic type of java.util.List

Categories