I create a class to handle some specific job that use variety of classes on my project.
But after finish the job class must call-back specific method on the called classes.
I use interface to handle this call-back method.
How can I store the called class?
I can get the instance from constructor but I'm looking for generic way.
Your question is not clear but it may be possible that you have missed the fact that classes can implement more than one interface.
public interface DoesAJob {
public void doIt();
}
public interface Finishes {
public void finish();
}
class AThing implements DoesAJob, Finishes {
#Override
public void doIt() {
}
#Override
public void finish() {
}
}
private void doTheJob(DoesAJob thing) {
thing.doIt();
}
private void finishUp(Finishes thing) {
thing.finish();
}
public void test() {
AThing thing = new AThing();
doTheJob(thing);
finishUp(thing);
}
You can use just Java Interface, or use Java Reflection.
First the Interface
package test;
public interface MyClassInterface {
public String getName();
}
next, the Interface Implementation
package test;
public class MyClassImplementation implements MyClassInterface {
String name;
public MyClassImplementation() {
name= "Whatever";
}
public String getName() {
return name;
}
}
finally invoke the class. just Interface example:
package test;
public class MainTest {
public static void main(String[] args){
MyClassInterface myClassImplementation = new MyClassImplementation();
System.out.println(myClassImplementation.getName());
}
}
Using Reflection example:
package test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MainTest {
public static void main(String[] args)
throws InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException, SecurityException {
//using reflection
Object otherClassImplementation=null;
try {
Class<?> cls = Class.forName("test.MyClassImplementation");
otherClassImplementation = cls.newInstance();
Method method = cls.getMethod("getName");
System.out.println(method.invoke(otherClassImplementation));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Related
I want to create a menu which should be populated by arbitrary methods, which are marked by an annotation. The methods should be invoked from inside the base class. Unfortunately 'java.lang.ClassCastException' is thrown since the method.invoke function expects an object which is instance of the child class. But i only get the base class.
Here is what i tried so far :
public abstract Class BaseClass{
private void invokeSomeMethod(){
final Method[] methods= getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(MenuFunction.class)) {
MenuFunction menuFunction = method.getAnnotation(MenuFunction.class);
menuFunction.invoke(this); //Throws 'java.lang.ClassCastException'
}
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ METHOD })
public #interface MenuFunction {
String Label();
}
}
public Class ChildClass extends BaseClass{
#MenuFunction(Label = "First method")
public void setHigh(){
//Arbitrary function
}
#MenuFunction(Label = "Another method")
public void setLow(){
//Do something
}
}
I guess what you want to do is this:
public abstract class BaseClass {
public void invokeSomeMethod() throws InvocationTargetException, IllegalAccessException {
final Method[] methods = getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(MenuFunction.class)) {
MenuFunction menuFunction = method.getAnnotation(MenuFunction.class);
method.invoke(this); //invoke method here'
}
}
}
}
public class ChildClass extends BaseClass{
#MenuFunction(Label = "hello")
public void hello() {
System.out.println("hello");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
new ChildClass().invokeSomeMethod();
}
}
Result:
hello
I have a main class as shown below. I want to Pass interface object to another method from Main method. I am Passing it as shown in my Main class below. But I am getting error "; expected". Can some one please help me?
This is my Main Class :
package com.armus.web.server;
import com.armus.common.dtflow.DfService;
public class TriggerAgain
{
public static void main(String[] args){
Long i= 97944605L;
DMSerImpl rdf = new DMSerImpl();
try {
/*********** Section start....Getting Problem In this section...How Can I Pass interface object to a method setDfService*********/
#Override
rdf.setDfService(new DfService()
{
Dfsessn dfsessn=getDfsessnById(i)
{
System.out.println("In main class...In interface method="+i);
}
})
/*************************************************Section End*******************************************************************/
com.armus.dto.Jinfo a=rdf.Trigger(i);
}
catch( Throwable e){
System.out.println("In exception = "+e+" "+i);
e.printStackTrace();
return; // Always must return something
}
}
}
This is my another class to which I want to Pass interface Object to "setDfService" Method.
package com.armus.web.server;
import com.armus.common.dtflow.DfService;
import com.armus.common.dto.Dfsessn;
import com.armus.foundation.client.exception.ServiceException;
import com.armus.dto.Jinfo;
public class DMSerImpl
extends Remoteservletsup
implements DMserv, DMAjxSer
{
private DfService dtflowser;
public void setDfService(DfService dtflowser)
{
this.dtflowser = dtflowser;
}
private Dfsessn getDfsessn(long sessionId)
throws ServiceException
{
try
{
dfSession = this.dtflowser.getDfsessnById(Long.valueOf(sessionId));
}
catch (ServerException e)
{
Dfsessn dfSession;
LOG.error(e.getMessage(), e);
throw new ServiceException(e.getMessage());
}
return dfSession;
}
public com.armus.dto.Jinfo Trigger(long sessionId)
throws ServiceException
{
Dfsessn dfSession = getDfsessn(sessionId);
//some code
}
}
Below is My Interface :
package com.armus.common.dtflow;
import com.armus.common.dto.Dfsessn;
import com.armus.common.exception.ServerException;
public abstract interface DfService
{
public abstract Dfsessn getDfsessnById(Long paramLong)
throws ServerException;
}
Thank you in Advance !!! :)
This is an example of creating an instance of an anonymous class
rdf.setDfService(new DfService() {
#Override
public Dfsessn getDfsessnById(Long paramLong) {
....
}});
You are:
Putting the #Override in the wrong place;
not declaring the method override properly; and
missing a closing semicolon:
rdf.setDfService(new DfService()
{
#Override
public Dfsessn getDfsessnById(Long i)
{
System.out.println("In main class...In interface method="+i);
}
});
#Override
rdf.setDfService(new DfService()
{
Dfsessn dfsessn=getDfsessnById(i)
{
System.out.println("In main class...In interface method="+i);
}
})
Above what you are trying to do is creating an anonymous class instance implementing the DfService interface but you are not doing it correctly(syntax wise).
Read about anonymous inner classes here https://www.geeksforgeeks.org/anonymous-inner-class-java/
Also, DfService is a functional interface(single method interface) so you can also use a lamda here. Something like this.
rdf.setDfService(paramLong -> System.out.println("In main class...In interface method="+i));
Take a look at this for more info https://javarevisited.blogspot.com/2015/01/how-to-use-lambda-expression-in-place-anonymous-class-java8.html
I want to define a function that creates different type objects that share the same base class. I'd like to pass in the object type and have the function creating the object and then modifying its attributes. The problem is that the main class from which all these objects are created, does not have the object's attributes so the code fails to compile.
Example:
public void new_generic_report(Class report_class, String report_name) {
Report new_report = this.reportManager.createReport(report_class);
new_report.set_name(report_name);
}
Calling new_generic_report(GreenReport.class, "green_report"); fails because new_report is of the class Report instead of GreenReport so it does not have the .set_name method.
I know I could implement the .set_name method (and other common methods) in the main Report class but I am writing code to interface with an API that I cannot modify.
If you are sure that createReport returns an instance of the correct class you can just do a cast:
((SpecialClass)new_report).set_name(report_name);
An alternative is to use reflection:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
static class Base {};
static class Child extends Base {
public void setName(final String name) {
System.out.println("setName("+name+")");
}
}
public static void main(String[] args) {
new Test().new_generic_report(Child.class, "Testname");
}
public void new_generic_report(final Class clazz, final String name) {
Base base = createBase(clazz);
try {
Method m = clazz.getMethod("setName", String.class);
m.invoke(base, name);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
private Base createBase(Class report_class) {
return new Child();
}
}
Of course this only works, if the returned instance implements the method.
Create a parent class for your report for instance :
public abstract class NamedReport extends Report
{
public abstract void setName(String name);
}
class GreenReport extends NamedReport {
#Override
public void setName(String name) {
}
}
Then simply cast your class in your method :
public void new_generic_report(Class report_class, String report_name) {
Report new_report = this.reportManager.createReport(report_class);
if (new_report instanceof NamedReport)
{
((NamedReport)new_report).set_name(report_name);
}
}
I have the following need and please help me to write good and abstract class.
Different types of operations is needed based on the type
I have a abstract class,
abstract public class FileHelper{
//Template method
//This method defines a generic structure for parsing data
public void parseDataAndGenerateFile(String fileDownloadType)
{
createHeader(fileDownloadType);
generateFile();
}
//We have to write output in a excel file so this step will be same for all subclasses
public void createHeader(String fileDownloadType)
{
System.out.println('Creating HEADER in EXCEL');
}
public void generateFile(String fileDownloadType)
{
System.out.println('Output generated,writing to XLX');
}
}
public class ExcelDataParser extends FileHelper {
String fileDownloadType="";
}
public class TemplateMethodMain {
public static void main(String[] args) {
String fileDownloadType="expired";
ExcelDataParser csvDataParser=new ExcelDataParser();
csvDataParser.parseDataAndGenerateFile(fileDownloadType);
}
}
Please help me and correct me to have a good way of doing this.
If you want to use an abstract base class, you better should declare an abstract method String getDownloadType() in your abstract base class. These method must be overridden by the derived classes and the type could be fix in the derived class.
For example:
abstract public class FileHelper {
abstract String getFileDownloadType();
public void parseDataAndGenerateFile() {
createHeader();
generateFile();
}
public void createHeader() {
if ("expired".equals(getFileDownloadType())) {
} else {
}
}
public void generateFile() {
if ("expired".equals(getFileDownloadType())) {
} else {
}
}
}
public class ExcelDataParser extends FileHelper {
#Override
String getFileDownloadType() {
return "expired";
}
}
public class TemplateMethodMain {
public static void main(String[] args) {
ExcelDataParser csvDataParser = new ExcelDataParser();
csvDataParser.parseDataAndGenerateFile();
}
}
But if you don't need a class for every type, you also could make the type a variable inside a single class and passing the type to the contructor
For example:
public class CsvFileHelper {
private final String fileDownloadType;
public CsvFileHelper(String type) {
fileDownloadType = type;
}
public void parseDataAndGenerateFile() {
createHeader();
generateFile();
}
public void createHeader() {
if ("expired".equals(fileDownloadType)) {
} else {
}
}
public void generateFile() {
if ("expired".equals(fileDownloadType)) {
} else {
}
}
}
public class TemplateMethodMain {
public static void main(String[] args) {
CsvFileHelper csvDataParser = new CsvFileHelper("expired");
csvDataParser.parseDataAndGenerateFile();
}
}
i want to use the method of my child class dynamically!
how can i access to child method?
the parent class is :
public abstract class A{
String temp;
public abstract String getData();
public void setData(String temp){
this.temp=temp;
}
and childs class is:
public class B extends A{
#Override
public String getData() {
return "B--GetData";
}
#Override
public void setData(String temp) {
this.temp= temp+"-B";
}
public class C extends A{
#Override
public String getData() {
return "C--GetData";
}
#Override
public void setData(String temp) {
this.temp= temp+"-C";
}
}
i use this code to access my child class
String parseData(String Name){
Class<?> cls = Class.forName(Name);
cls.getMethods();
}
how can i able to call for example getData() method from class C dynamically?
thanks
public String parseData(String Name) throws Exception {
Class<?> cls = Class.forName(Name);
Method[] methods = cls.getMethods();
for (Method method : methods) {
if(method.getName().equals("setData")) {
method.invoke(cls.newInstance(), "Test");
}
}
return null;
}
Please try to use like that.
You call method like below
parseData(C.class.getName());
You can call your method like this :
methods[0].invoke(new B(), null);
you can use `method[1]` or `new C()` based on which method to call and on which object.
The below code also shows how to access private methods as well.
Example :
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
class ExitPuzzle extends MyAbstractClass {
public static void main(String... args) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Class clazz = MyAbstractClass.class;
Method[] methods = clazz.getDeclaredMethods();
System.out.println(Arrays.toString(methods));
methods[0].setAccessible(true); // needed only if method is non-public
methods[0].invoke(new ExitPuzzle(), null);
}
}
abstract class MyAbstractClass {
private void myMethod() {
System.out.println("in MyAbstractClass");
}
}