How can I dynamically create an instance of a class in java? - java

I would like to create an object dynamically.
I have the following structure:
1 abstract class and several classes that inherit from the abstract class
abstract public class A {..}
public class B extends A{..}
public class C extends A{..}
I have a config file where i want to add a class name, to have the ability to control which class it should be used.
# config class name
classname = B
I tried the following, but here I have the problem that I have to cast the result
and I do not know how I can do it dynamically at this point
public class TestClass {
public A instB;
public void getInstance(){
this.instB = Class.forName("B") /*here i put later the config value classname*/
.getConstructor(String.class)
.newInstance(new Object[]{"test"}); // <--- How to cast this dynamicly to a class in the config?
}
}
How can I dynamically create an instance of a class?

Just cast it to A:
instB = (A)Class....newInstance(...);
You don't need to know the exact class.

I don't see the point of why you really need to use reflection. I would suggest using a simple strategy pattern, for example:
Strategy.java
public interface Strategy {
void doWork();
}
StrategyA.java
public class StrategyA implements Strategy {
#Override
public void doWork() {
}
}
Strategy B.java
public class StrategyB implements Strategy {
#Override
public void doWork() {
}
}
Main.java
public class Main {
public static void main(String[] args) {
// read the option from a config file
String option = "B";
Strategy strategy = createStrategy(option);
// create a context with the strategy
MyContext context = new MyContext(strategy);
context.doWork();
// config has changed dynamically, change the strategy
context.useStrategy(new StrategyA());
context.doWork();
}
public static Strategy createStrategy(String strategy) {
if (strategy.equals("A")) {
return new StrategyA();
}
return new StrategyB();
}
}
MyContext.java
public class MyContext {
Strategy strategy;
public MyContext(Strategy strategy) {
this.strategy = strategy;
}
public void useStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void doWork() {
strategy.doWork();
}
}

Related

Handle duplicate code in concrete implementations of an interface in Spring boot application

I am working on a spring boot application, where I have an interface I as follows:
public interface I {
String getType();
void f1();
}
There are two classes implementing interface I as follows:
#Component
class A implements I {
private final MyRepo1 myRepo1;
private final Helper helper;
public A(MyRepo1 myRepo1, Helper helper) {
this.myRepo1 = myRepo1;
this.helper = helper;
}
#Override
public String getType() {
return "type1";
}
#Override
public void f1(String type) {
int response = helper.f1(type);
if(response != -1) {
return;
}
//Add type1 specific handling here
}
}
One more class B implementing interface I as follows:
#Component
class B implements I {
private final MyRepo2 myRepo2;
private final Helper helper;
public B(MyRepo2 myRepo2, Helper helper) {
this.myRepo2 = myRepo2;
this.helper = helper;
}
#Override
public String getType() {
return "type2";
}
#Override
public void f1(String type) {
int response = helper.f1(type);
if(response != -1) {
return;
}
//Add type2 specific handling here
}
}
Helper is as follows:
#Component
class Helper {
public int f1(String type) {
...
}
}
I have a factory class as follows, that is used to fetch an object of the appropriate type:
#Component
public class ServiceFactory {
private final Map<String, I>
typeToClassMap = new HashMap<>();
public ServiceFactory(List<I> components) {
for(I component : components) {
typeToClassMap.put(component.getType(), component);
}
}
}
This ServiceFactory is basically used to get objects according to the type.
Now, the problem is, here for sake of simplicity I have just shown two classes implementing the interface. But actually, I have a lot more classes than this, implementing the interface I.
Some of the classes may have the same implementation of f1(), resulting in duplicate code.
I cannot make f1() as the default method in interface I as this requires the dependent bean.
I cannot understand what is the best way to handle this.
Could anyone please help here?

Abstract class with visitor - similar to typeOf

I am little confused how to avoid using casing in my manager method (last snippet of code) in terms of abstract class with it's derived classes (entities) and visitor design pattern eventually. Below I have an abstract class for entities called BaseEntity. It's not a real example, just pseudocode.
public abstract class BaseEntity {
#Reference
protected List<String> items = new ArrayList<>();
public BaseEntity() {
}
public List<String> getItems() {
return items;
}
public void setItems(List<String> items) {
this.items = items;
}
}
Below I have 3 derived classes from abstract class.
#Entity("CollectionA")
public class EntityA extends BaseEntity {
//code
}
#Entity("CollectionB")
public class EntityB extends BaseEntity {
//code
}
#Entity("CollectionC")
public class EntityC extends BaseEntity {
//code
}
Then I created an visitor to reuse that in my manager to avoid using instanceOf.
public interface UpdateEntityVisitor {
void create(EntityA entityA);
void create(EntityB entityB);
void create(EntityC entityC);
}
public class UpdateEntityVisitorImpl implements UpdateEntityVisitor {
private final Factory factory;
public UpdateEntityVisitorImpl() {
factory = new FactoryImpl();
}
public UpdateEntityVisitorImpl(Factory factory) {
this.factory = factory;
}
#Override
public void create(EntityA entityA) {
factory.getEntityA().create(entityA);
}
#Override
public void create(EntityB entityB) {
factory.getEntityB().create(entityB);
}
#Override
public void create(EntityC entityC) {
factory.getEntityC().create(entityC);
}
}
And finally it's my manager class which has below method, where I would like to avoid casting down from BaseEntity to appropriate classes. There is a way to achieve that reusing above visitor class in manager ?
public void updateEntity(BaseEntity entity) {
if (checkSmth()) {
updateCollectionA((EntityA) entity);
} else {
updateCollectionB((EntityB) entity);
}
}
I found this very useful library called typeOf https://github.com/nurkiewicz/typeof but I was wondering if there is other way to make it more clear to my current team.
Does using generics work?
public <T extends BaseEntity> void updateEntity(T entity)
{
if (checkSmth())
updateCollectionA(entity);
else
updateCollectionB(entity);
}

Class instantiated elsewhere and this is used to access it

I am trying to play around with class instantiation and this.
In the below example, the testresult class will be instantiated and stored.
this will be used to pass that class instance as a parameter to another class.
Is this proper usage of this as the class is instantiated elsewhere?
Not sure why I see error as "The constructor testfail(new Handler(){}) is undefined".
Code snippet:
public class testmain {
private testresult tr;
private testfunc tf;
public testmain() {
tr = new testresult();
tf = new testfunc(tr);
}
}
public class testfunc {
private testresult storeit;
public testfunc(testresult inst) {
storeit = inst;
}
// this will be running as seperate thread running forever.
}
public class testresult {
private testfail tp;
public void function() {
tp = new testfail(this); //----> error new Handler(){} undefined
}
}
public class testfail {
public testfail(testresult tr) {
///
}
}
Edit : The error due to inner class
public class testresult {
private testfail tp;
private class test {
public void function() {
tp = new testfail(this); ----> error
// new Handler(){} undefined
}
}
}
As written, your code will compile. Because testfail accepts an argument of testresult, using this will work, even though it's awkward and not something one normally sees.
Unless you overrode your testfail constructor by introducing another constructor that accepted a Handler as an argument, this compilation failure is expected.
As an example:
public class testfail {
public testfail(testresult tr) {
///
}
public testfail(Handler hr) {
}
}

Passing parameter to anonymous class in Java

i'm trying to write anonymous inner class
interface Face{
void seeThis(String what);
}
class Eyes {
public void show(Face f){}
}
public class Seen {
public void test() {
Eyes e = new Eyes();
e.show(new Face() {
#Override
public void seeThis(String what){
System.out.print(what);
}
});
public static void main(String[] args) {
Seen s = new Seen();
s.test();
}
}
How to call seeThis() and how to pass parameter to it?
Method seeThis() belongs to Face class, which instance is anonymous and thus cannot be reached without storing reference to it. If you want to store a reference, you can do this in the following way:
public class Seen {
public Face face;
....
this.face = new Face() { ... };
e.show(this.face);
And then,
Seen s = new Seen();
s.face.seeThis();
Now, regarding passing the parameter. You have two options - declare parameter outside of anonymous class and make it final in order to be reachable by this anonymous class, or replace anonymous class with normal one and pass the parameter to its constructor:
Approach one:
final int parameter = 5;
...(new Face() {
#Override
public void seeThis() {
System.out.println(parameter);
}
});
Approach two:
public class MyFace implements Face() {
private final int parameter;
public MyFace(int parameter) {
this.parameter = parameter;
}
#Override
public void seeThis() {
System.out.println(parameter);
}
}
Then,
...
e.show(new MyFace(10));

Instantiating generic class and implementing generic interface

I have this class:
public DrawItem {
protected String getSeperator() {
return "";
}
.......
// some other methods
}
I've another class which extends DrawItem.
public DrawNumber extends DrawItem {
#Override
protected String getSeperator() {
return "-";
}
}
Now, in a generic class CombinationGenerator<E>, I'm trying to instantiate objects of DrawItem/DrawNumber. As instantiating a generic type is not possible in java (like new E(...)), I've created a Factory interface according to this answer.
public interface DrawItemFactory<E> {
E create(...);
}
Then in the CombinationGenerator<E> class,
public class CombinationGenerator<E> {
DrawItemFactory<E> factory;
public CombinationGenerator<E>(DrawItemFactory<E> factory) {
this.factory = factory;
}
public List<E> generate() {
......
list.add(factory.create(...));
......
}
}
And now the DrawNumber class implements DrawItemFactory<DrawItem> interface.
public DrawItem implements DrawItemFactory<DrawItem> {
protected String getSeperator() {
return "";
}
#Override
public DrawItem create(...) {
return new DrawItem(...);
}
.......
// some other methods
}
And I can create CombinationGenerator<DrawItem> class.
DrawItem drawItem = new DrawItem(...);
CombinationGenerator<DrawItem> generator = new CombinationGenerator<DrawItem>(drawItem);
List<DrawItem> combinations = generator.generate();
So far, everything is fine. But when I try to create a DrawNumber class like this,
public DrawNumber implements DrawItemFactory<DrawNumber> {
....
}
It gives me the following error:
The interface DrawItemFactory cannot be implemented more than once with different arguments: DrawItemFactory<DrawItem> and DrawItemFactory<DrawNumber>
I've tried this solution but I got the same error. Is there any other way to do this?
Instead of using all those factories you could do something like this:
public class CombinationGenerator<E> {
E instance;
public CombinationGenerator(Class<E> clazz) {
Constructor<?> con = clazz.getConstructor();
this.instance = (E) con.newInstance();
}
}
...
CombinationGenerator<DrawNumber> cg = new CombinationGenerator<DrawNumber>(DrawNumber.class);
According to #JB Nizet's comment, I've solved the problem by creating two separate factory classes like this:
public interface ItemFactory<E> {
E create(int[] values);
public static class DrawItemFactory implements ItemFactory<DrawItem> {
#Override
public DrawItem create(int[] values) {
return new DrawItem(values);
}
}
public static class DrawNumberFactory implements ItemFactory<DrawNumber> {
#Override
public DrawNumber create(int[] values) {
return new DrawNumber(values);
}
}
}
In the CombinationGenerator,
public class CombinationGenerator<E> {
ItemFactory<E> factory;
public CombinationGenerator<E>(ItemFactory<E> factory) {
this.factory = factory;
}
public List<E> generate() {
......
list.add(factory.create(...));
......
}
}
And instantiated CombinationGenerator like this:
DrawNumber drawNumber = new DrawNumber();
CombinationGenerator<DrawNumber> generator = new CombinationGenerator<DrawNumber>(new ItemFactory.DrawNumberFactory());
List<DrawNumber> combinations = generator.generate();

Categories

Resources