How to execute method on object of Class<?> - java

I wonder is it possible to execute method from class on runtime on object of Class?
At first: I have method that returns me a class:
public static Class<?> getClassById(Long id) throws ClassNotFoundException {
if(d.id == 1L) {
return First.class;
} else if(d.id ==2L) {
return Second.class;
} else if(d.id ==3L) {
return Third.class;
} else {
throw new ClassNotFoundException();
}
}
Second: The way I execute it:
Index.GetClassById(1) which should return me Class. Now I would like to execute method myMethod() from that class. By the way, each class of (First, Second, Third) have this myMethod() method.
Please help.

A Class object is an instance of the type representing your class. This means that First.class.equals(new First()) will always return false.
What you want is to create an object based on your class and on that class call your method myMethod(), assuming that you classes (First, Second, Third) have a default constructor:
Class clazz = Index.getClassById(1);
First first = (First)clazz.newInstance();
first.myMethod();
The drawback on this approach is that you have to cast the object explecitly.
For this to relay work neatly you should define an interface that defines myMethod():
public interface MyInterface {
void myMethod();
}
public class First implements MyInterface {
...
}
public class Second implements MyInterface {
...
}
public class Third implements MyInterface {
...
}
Then you can define your method from above as:
public static Class<MyInterface> getClassById(Long id) throws ClassNotFoundException {
if(d.id == 1L) {
return First.class;
} else if(d.id ==2L) {
return Second.class;
} else if(d.id ==3L) {
return Third.class;
} else {
throw new ClassNotFoundException();
}
}
And call it like this:
Class<MyInterface> clazz = Index.getClassById(1);
MyInterface instance = clazz.newInstance();
instance.myMethod();

Since you have a class instance, you can get it's object instance and then invoke it's method by method's name:
//empty patameters array, to specify the method signature
Class noparams[] = {};
//get the class
Class cls = getClassById(1L);
//get an instance of the class
Object obj = cls.newInstance();
//get some method of the class by it's signatute (name and input parameters)
Method method = cls.getDeclaredMethod("myMethod", noparams);
//invoke this method without parameters
method.invoke(obj, null);
But the solution with some common interface is preferable, then you can get an instance of this interface and call it in usual way.

The problem that you talk about is a design pattern called abstract design pattern in which all your classes.
Step 1
Create an interface for Shapes.
Shape.java
public interface Shape {
void draw();
}
Step 2
Create concrete classes implementing the same interface.
Rectangle.java
public class Rectangle implements Shape {
#Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Square.java
public class Square implements Shape {
#Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Circle.java
public class Circle implements Shape {
#Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
Step 3
Create an interface for Colors.
Color.java
public interface Color {
void fill();
}
Step4
Create concrete classes implementing the same interface.
Red.java
public class Red implements Color {
#Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
Green.java
public class Green implements Color {
#Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
Blue.java
public class Blue implements Color {
#Override
public void fill() {
System.out.println("Inside Blue::fill() method.");
}
}
Step 5
Create an Abstract class to get factories for Color and Shape Objects.
AbstractFactory.java
public abstract class AbstractFactory {
abstract Color getColor(String color);
abstract Shape getShape(String shape) ;
}
Step 6
Create Factory classes extending AbstractFactory to generate object of concrete class based on given information.
ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
#Override
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
}else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
#Override
Color getColor(String color) {
return null;
}
}
ColorFactory.java
public class ColorFactory extends AbstractFactory {
#Override
public Shape getShape(String shapeType){
return null;
}
#Override
Color getColor(String color) {
if(color == null){
return null;
}
if(color.equalsIgnoreCase("RED")){
return new Red();
}else if(color.equalsIgnoreCase("GREEN")){
return new Green();
}else if(color.equalsIgnoreCase("BLUE")){
return new Blue();
}
return null;
}
}
Step 7
Create a Factory generator/producer class to get factories by passing an information such as Shape or Color
FactoryProducer.java
public class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("SHAPE")){
return new ShapeFactory();
}else if(choice.equalsIgnoreCase("COLOR")){
return new ColorFactory();
}
return null;
}
}
Step 8
Use the FactoryProducer to get AbstractFactory in order to get factories of concrete classes by passing an information such as type.
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//get shape factory
AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
//get an object of Shape Circle
Shape shape1 = shapeFactory.getShape("CIRCLE");
//call draw method of Shape Circle
shape1.draw();
//get an object of Shape Rectangle
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//call draw method of Shape Rectangle
shape2.draw();
//get an object of Shape Square
Shape shape3 = shapeFactory.getShape("SQUARE");
//call draw method of Shape Square
shape3.draw();
//get color factory
AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
//get an object of Color Red
Color color1 = colorFactory.getColor("RED");
//call fill method of Red
color1.fill();
//get an object of Color Green
Color color2 = colorFactory.getColor("Green");
//call fill method of Green
color2.fill();
//get an object of Color Blue
Color color3 = colorFactory.getColor("BLUE");
//call fill method of Color Blue
color3.fill();
}
}
Step 9
Verify the output.
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
Source :- http://www.tutorialspoint.com/design_pattern/abstract_factory_pattern.htm

Of course you can. Having a Class you can now instantiate it
Object t = c.newInstance()
where c is the Class<?> returned from your method.
Now you can do
Method m = c.getMethod("your_method_name", optional_params_classes_here);
Object result = m.invoke(t, params_here_or_nothing);

Use java reflections. Here is an example of calling 'concat' method of String s :
String s = "Hello, ";
Class myClass = s.getClass();
Method m = myClass.getDeclaredMethod("concat", String.class);
String result = (String)m.invoke(s, "world");
System.out.println(result);

Related

Java: Shortening enum call in method

Is there a way of shortening enum array call in method to {red, blue}?
interface PropertiesInterface {
enum Color {red, blue, yellow}
public void setColor(Color[] color);
}
class Car {
public PropertiesInterface setProperties() {
return new Properties();
}
private class Properties implements PropertiesInterface {
#Override
public void setColor(Color[] color) {
// TODO Auto-generated method stub
}
}
}
public class MyCar {
public static void main(String[] args) {
Car car = new Car();
car.setProperties().setColor(new PropertiesInterface.Color[] {PropertiesInterface.Color.red, PropertiesInterface.Color.blue});
car.setProperties().setColor(new PropertiesInterface.Color[] {red, blue});
}
}
import static com.yourcompany.PropertiesInterface.Color.*;
You can then reference as just {red, blue}
I don't think it is possible. As long as your enum is inside the Properties Interface interface, you must write the phrase "Properties Interface" twice when calling the enum. Maybe you should try making the name of the interface shorter.

passing different type of objects dynamically on same method

I want to write a method which would receive different type of objects dynamically. Once I receive the dynamic object, I have logic inside method to do something based on the properties associated with that object. It would be something like below:
MainClass{
class1 obj1;//all these are pojo
class2 obj2;
class3 obj3;
method1(<dynamic_object>)
}
method1(<dynamic_object>){
if(dynamic_object.property 1 == true){
callmethod2(dynamic_object.property 1)
}
else{
callmethod3(dynamic_object.property 1)
}
}
Here dynamic_objects are of different type.
How can I achieve this in Java? I do not want to use reflection here.
In order to recognize the type of the object you can use the instanceof operator.
private void instanceOfMethodExample(Object object){
if(object instanceof String)
print("Its a String!");
else if(object instanceof Integer)
print("Its an Int!");
else
print("Its a " + object.getClass().getName()); // by calling getClass().getName() method you take the class name of the object as a String
}
Use the visitor pattern, In a nutshell you can have something like this:
public class Visitor {
interface UserVisitor {
public void visit(CarUser user1);
public void visit(BusUser user2);
}
static class VehicleVisitor implements UserVisitor {
private Car vehicle;
private Bus bus;
VehicleVisitor(Car vehicle, Bus bus) {
this.vehicle = vehicle;
this.bus = bus;
}
public void visit(CarUser user1) {
user1.setCar(vehicle);
}
public void visit(BusUser user2) {
user2.setBus(bus);
}
}
interface UserVisitorClient {
void accept(UserVisitor visitor);
}
static class CarUser implements UserVisitorClient {
private Car car;
public void accept(UserVisitor visitor) {
visitor.visit(this);
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
}
static class BusUser implements UserVisitorClient {
private Bus bus;
public void accept(UserVisitor visitor) {
visitor.visit(this);
}
public void setBus(Bus bus) {
this.bus = bus;
}
public Bus getBus() {
return bus;
}
}
static class Car {
#Override
public String toString() {
return "CAR";
}
}
static class Bus {
#Override
public String toString() {
return "BUS";
}
}
public static void main(String[] args) {
List<UserVisitorClient> users = new ArrayList<UserVisitorClient>();
CarUser user1 = new CarUser();
users.add(user1);
BusUser user2 = new BusUser();
users.add(user2);
for (UserVisitorClient user : users) {
VehicleVisitor visitor = new VehicleVisitor(new Car(), new Bus());
user.accept(visitor);
}
System.out.println(user1.getCar());
System.out.println(user2.getBus());
}
}
Which is just an example. But it shows that basically you can use this pattern to support what you're trying to accomplish.
In your code, you could have:
void method1(VisitorClient client) {
client.accept(someVisitor);
}
This will allow you to reach o more object oriented solution, relying in polymorphism instead of reflection or instanceof.
The best option is to use a common interface
interface HasProperty {
boolean isSet();
}
void method1(HasProperty object) {
if (object.isSet())
method2(object);
else
method3(object);
}
Or even better have a method to call to perform an action.
interface MethodOne {
void method1();
}
MethodOne object = ...
object.method1(); // calls the appropriate method for this object.
Use superclass of all objects- "Object" and check the type of object using instanceof operator.
method1(Object obj){
if(obj instanceof dynamic_object){
callmethod2(dynamic_object.property 1)
}
else if(obj instanceof dynamic_object2) {
callmethod3(dynamic_object2.property 1)
}
}
EDIT: Given your newly posted code, you may even simply wish to use an common interface, or base class, for the dynamic objects.
Interface:
public interface CommonInterface {
boolean isValid();
void method1();
void method2();
void method3();
}
Class Example:
public Class1 implements CommonInterface {
public boolean isValid() {
return true;
}
public void method1() {
System.out.println("Method 1");
}
public void method2() {
System.out.println("Method 2");
}
public void method3() {
System.out.println("Method 2");
}
}
Code:
public void doSomethingWithCommonObjects(CommonInterface object) {
object.method1();
if (object.isValid()) {
object.method2();
} else {
object.method3();
}
}
Each of the dynamic objects simply need to implement the CommonInterface interface, which would enforce method1(), method2(), method3() and property1() signatures for each object to implement.
Previous answer details for reference:
You will either have to use Java Generics, potentially with some common interface or base class for the objects in question so that you can then call their methods.
E.g.
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x; // assume x is initially the largest
if (y.compareTo(max) > 0) {
max = y; // y is the largest so far
}
if (z.compareTo(max) > 0) {
max = z; // z is the largest now
}
return max; // returns the largest object
}
If, however, you require to call particular methods without knowing the interface for those methods beforehand programmatically, then you're into Reflection territory.

How to correctly use the visitor pattern with different Shapes for an Editor

I am creating a editor for different Shape Objects. I stumbled upon the visitor pattern which actually fits my needs I think.
I have a Element class which holds a field named attrs
public class Element {
...
private Shape attrs;
...
}
My Shape class looks like this with the visitor design pattern.
public abstract class Shape {
public abstract void accept(ShapeVisitor v);
public interface ShapeVisitor{
public void visit(CircleObject circle);
public void visit(RectangleObject rectangle);
}
}
And the actual instance of a Shape is defined in a RectangleObject class which extends Shape and holds the Rectangle field. The reasoning for this structure is that I am serializing and deserializing with Jackson for a specifig JSON layout.
public class RectangleObject extends Shape {
private Rectangle rect;
public class Rectangle {
private String fill;
public String getFill() {
return fill;
}
public void setFill(String fill) {
this.fill = fill;
}
#Override
public void accept(JointShapeVisitor v) {
v.visit(this);
}
}
And finally my Editor implements the vistor methods.
public class Editor implements ShapeVisitor{
#Override
public void visit(CircleObject circle) {
}
#Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
visit(element.getAttrs()); // *** this does obv. not work ***
}
}
The element.getAttrs() returns JointShape, but I need here a CircleObject or a RectangleObject.
How can I pass the correct instance of the ShapeObject to the visit method? Am I doing something completely wrong?
Best regards.
Well ... one little mistake. Because you correctly declared an accept method in your Shape class, you simply must call it:
element.getAttrs().accept(this);
So simply call the accepting method of a shape by providing the editor itself as a visitor. The callback in the shape implementation will call the correct visitor mehod.
What you would do is
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
element.getAttrs().accept(this);
}
And you'll get a callback into one of the visit methods. What you don't get is a return value.
This can be a bit tricky to handle because the callback code is suddenly in no relation to the method that called the accept method. But you often want to pass arguments back and forth between the visiting method and the method that that called accept. To do that, you can add a little to the pattern:
#Override
public Object accept(JointShapeVisitor v, Object context) {
return v.visit(this, context);
}
}
public interface ShapeVisitor{
public Object visit(CircleObject circle, Object context);
..
}
Maybe with a bit of generics to make it typesafe. But even without you can suddenly do
public class Editor implements ShapeVisitor{
#Override
public Foo visit(CircleObject circle, Object context) {
return new Foo(circle, (String) context));
}
#Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
Foo foo = (Foo)element.getAttrs().visit(this, "Hello");
}
}

AbstractFactory design pattern in real life

As you all know that the AbstractFactory helps creating object without knowledge of creation process. But the complexity of the pattern will increase by the time, when new factory is added or large modifications are made within the factory class. This will require a heavy change on abstract factory creator class.
I used to use AbstractFactory, but with my own modification & it's like: Replace abstract factory creator class with empty interface, which will be implemented by factory classes. Then cast returned object from FactoryCreator class to the real factory I want. This worked, but I wonder if this breaks the pattern or is it a bad practice on the pattern or does it have any drawback that would lead to the same complexity in the future development?
Below is a very simple implementation of the pattern that I took from the book & my modifications as well:
Shape factory:
public interface Shape {
void draw();
}
public class Circle implements Shape {
#Override
public void draw() {
// Draw circle
}
}
public class Rectangle implements Shape {
#Override
public void draw() {
// Draw rectangle
}
}
public class ShapeFactory implements IFactory {
public Shape getShape(String shape) {
if (shape.equalsIgnoreCase("CIRLE")) {
return new Circle();
} else if (shape.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
return null;
}
}
//public class ShapeFactory extends AbstractFactory {
// #Override
// public Color getColor(...) {
// //
// }
// #Override Shape getShape(...) {
// //
// }
//}
Color factory:
public interface Color {
void fill();
}
public class Red implements Color {
#Override
public void fill() {
// Fill red
}
}
public class Green implements Color {
#Override
public void fill() {
// Fill green
}
}
public class ColorFactory implements IFactory {
public Color getColor(String color) {
if (color.equalsIgnoreCase("RED")) {
return new Red();
} else if (color.equalsIgnoreCase("GREEN")) {
return new Green();
}
}
}
//public class ColorFactory extends AbstractFactory {
// #Override
// public Color getColor(...) {
// //
// }
// #Override Shape getShape(...) {
// //
// }
//}
Factory creator interface:
public interface IFactory { }
//public abstract class AbstractFactory {
// abstract Color getColor(String color);
// abstract Shape getShape(String shape) ;
//}
Factory creator:
public class FactoryCreator {
public static IFactory getFactory(String factoryName) {
if (factoryName.equalsIgnoreCase("SHAPE")) {
return new ShapeFactory();
} else if (factoryName.equalsIgnoreCase("COLOR")) {
return new ColorFactory();
}
return null;
}
}
Usage:
public class demo {
ShapeFactory shapeFactory = (ShapeFactory)FactoryCreator.getFactory("SHAPE");
ColorFactory colorFactory = (ColorFactory)FactoryCreator.getFactory("COLOR");
shapeFactory.getShape("CIRCLE").draw();
shapeFactory.getShape("RECTANGLE").draw();
colorFactory.getColor("RED").fill();
colorFactory.getColor("GREEN").fill();
}
So the question in essence boils down to difference between abstract class and interface.
There are many sources on this discusion:
see here
What you need to understand about the patterns is that they are designed to be template for solution. It will happen rarely that you can copy paste pattern with zero modification and expect to fit your problem perfectly.
As for your question, can you implement AbstractFactory pattern with a FactoryCreator interface instead of abstract class ?
Surely you can, this is an implementation detail which does not break the intent of the pattern.
Abstract Factory offers the interface for creating a family of related objects, without explicitly specifying their classes.
Edit
You are looking at one specific implementation of this pattern in which author decided to implement the template with abstract class.
Design patterns are not a guarantee to to the right thing... you have to use your head first...
history showed that many people had a certain problem with [xxx] and a lot of people could solve the problem with Design-Pattern [yyy]. That's how desgin pattern evoveld and how they are defined.
You cannot say i'll implement this (or that) pattern and i'll have no problems anyway. you have to think, describe your problem and see if this pattern would help you to design your architecture.
Obviously: your programm implementation is so simple that abstractFactory is overhead, and you already solved that with using mere interfaces.
ok, let's speak the obvoius:
AbstractFactory is not the solution to your problem:
first: define your problem: i want to create parametrized objects in a simple way. a) parametrized with shape and color and b) simple way
possible solution: factory-methode (think: you have the interface Shape with two implementations and the interface Color with two implementations)
public ShapeFactory{
public static Shape create(String shape){
if ("CICRCLE".equals(shape)) //your code from above
}
}
and a Color factory
public ColorFactory{
public static Color createColor(String color){
if("GREEN".equals(color) ) // your code from above
}
}
using these design pattern you can solve your problem as defined above... (you can make one factory wich provides factory-methods for both interfaces, if you want to make it even shorter)
As per my understanding in the above problem, one wants to create a shape and then fill color in it. If thats the case one can make it bit better by adding Builder pattern on top of factory.
class ShapeBuider
{
private String color;
private String shape;
/**
* #param color the color to set
*/
public void setColor(String color) {
this.color = color;
}
/**
* #param shape the shape to set
*/
public void setShape(String shape) {
this.shape = shape;
}
public void build()
{
// create shape
// create color
// fill shape with color
}
public Object get()
{
// return the created object in build method here.
return null;
}
}
This builder approach will make sure that the right color is applied to right shape.

Calling method from abstract class

I have the following abstract class
public abstract class ReturnAgentFromTab extends BasePage{
#Persist("session")
public abstract Agent getAgent();
public abstract void setAgent(Agent agent);
#InjectObject("spring:agentApplicationModeResolver")
public abstract AgentApplicationModeResolver getAgentApplicationModeResolver();
.... more #InjectObject()
public void nextPage(IRequestCycle cycle) {
setApplicationModeUsingAgentStatus(getAgent());
AgentSearchNavigationManager navManager = getAgentSearchNavigationManagerFactory().getAgentSearchNavigationManager();
FlowStage stage = getFlowStage();
if (stage == null) {
setApplicationModeUsingAgentStatus(getAgent());
stage = getUserDefaultFlowStageService().getDefaultFlowStage(UserHolder.getUser(), getVisitClass().getApplicationMode());
}
Class nextPageClass = navManager.getNextPage(getUserDefaultFlowStageService());
String nextPageQualifier = getUserDefaultFlowStageService().getPageQualifier(getAgent(), nextPageClass, getVisitClass().getApplicationMode());
IPage nextPage = getPageUtils().getPage(nextPageClass, nextPageQualifier);
if ((getFlowStage() instanceof PSDFlowStage)) {
nextPageQualifier = getFlowStage().getValue();
}
nextPage = getPageUtils().getPage(nextPageClass, nextPageQualifier);
if (navManager instanceof NameBasedAgentSearchNavigationManager && nextPageClass != SignOffStatusPage.class) {
NameBasedAgentSearchNavigationManager nameBasedNavManager = (NameBasedAgentSearchNavigationManager) navManager;
String nextPageName = nameBasedNavManager.getNextPageName(stage);
if (!nextPageName.equals(nextPageClass.getSimpleName())) {
nextPage = getPageUtils().getPage(nextPageName, nextPageQualifier);
}
}
if (isNextPageActivateAgentGeneral(nextPage)) {
initialisePageLink(nextPageClass, nextPage);
}
((WuamsBasePage) nextPage).init(getAgent().getAgentId());
getPageUtils().navigateTo(nextPage);
}
private void setApplicationModeUsingAgentStatus(Agent agent) {
getVisitClass().setApplicationMode(getHomeLinksFactory().getRegionHomeLinksService().getApplicationMode(agent));
}
private boolean isNextPageActivateAgentGeneral(IPage nextPage) {
return nextPage instanceof ActiveAgentGeneralPage;
}
private void initialisePageLink(Class nextPageClass, IPage nextPage) {
if (getVisitClass().getPageLink() == null) {
getVisitClass().setPageLink(PageLinkUtil.getPageLinkMessageKeyFromPageClass(nextPageClass,
getUserDefaultFlowStageService().getDefaultFlowStage(UserHolder.getUser(), getVisitClass().getApplicationMode()).getValue()));
}
}
}
What I want to do is call my nextPage(cycle) from another class that is abstract and extends ReturnAgentFromTab, but when I try
public abstract class DoSomethingWithAgent extends ReturnAgentFromTab {
#Persist("session")
public abstract ReturnAgentFromTab getReturnAgentFromTab();
public abstract void setReturnAgentFromTab(ReturnAgentFromTab returnAgentFromTab);
....
getReturnAgentFromTab().nextPage(cycle);
I get a null pointer exception, I know this is because I am not actually setting ReturnAgentFromTab anywhere but I do not understand how to set it using abstract classes. Can anybody help?
If ye need more code just ask
The point of abstract classes is to simply not implement certain things, such as providing certain objects. The method getReturnAgentFromTab() is a perfect example: the class itself does not care where that object comes from because that is the sole responsibility of the subclass. So extend that class, write that method, and all of a sudden the base class does its thing.
well, you cant intialize abstract class, the only way is to make some other concrete class extend your abstract class, and call the non abstract method with the concrate classes instance.
abstarct class ABS1 {
//abstract methods
//concreate method
public void concMethod() {
}
}
public class ABS1Impl extends ABS1 {
//implement all the abstract methods
}
public abstract class ABS2 {
ABS1 abs = new ABSImpl();
abs.concMethod //
}

Categories