I have a two simple class and use reflection pattern for invoke method.
I want to write module programming.
Suppose we have a table in database that keep modules name:
Id moduleName methodName ClassName active
1 sample a com.examle.sample true
2 SMS sendSMS com.example.SMS false
3 Email sendEmail com.example.Email false
... ... ... ...
When active is true the module must be activated.So when i write a program and compile that, i do not like again compile whole MyApp. So i use reflection pattern to invoke module. please see the codes.
public class Sample {
public void a() {
System.out.println("Call Method a");
}
}
public class SMS {
public void sendSMS(String str) {
System.out.println("send SMS ok");
}
}
public class Email {
public void sendEmail(String str) {
System.out.println("send Email ok");
}
}
public class SampleMainClass {
public static void main(String[] args) {
//coonect to database and fetch all record in tables
while(record.next){
if (record.getActive()){
Object o = Class.forName(record.getClssName()).newInstance() ;
Method method = o.getClass().getDeclaredMethod(record.getMethodName());
method.invoke(o);
}
}
}
output
Call Method a
So i heard in the java 8, reflection pattern is deprecate and instead that we can use consumer and supplier.
How to use consumer and supplier instead Reflection in java 8?
Thanks.
public class Q42339586 {
static class Sample {
void a() { System.out.println("a() called"); }
void b() { System.out.println("b() called"); }
}
static <T> void createInstanceAndCallMethod(
Supplier<T> instanceSupplier, Consumer<T> methodCaller) {
T o = instanceSupplier.get();
methodCaller.accept(o);
}
public static void main(String[] args) {
createInstanceAndCallMethodJava8(Sample::new, Sample::a);
}
}
Here, createInstanceAndCallMethod does what is done in your main() Method but it accepts parameters instead.
A Supplier is used to create a new instance and a Consumer is used to call a particular method on that instance. In the example both method references are passed as both parameters. Instead, you could also use lambda expressions and write () -> new Sample() and o -> o.a() instead. Please refer to this official tutorial part for more information.
The advantages over reflection are obvious:
You cannot ask createInstanceAndCallMethod to create an instance of a class that doesn't exist.
You cannot ask createInstanceAndCallMethod to call a method that doesn't exist in a particular class.
As a result of both you don't have to deal with any checked Exception.
Of course this does only work when at some place in the code the actual class and method are known, e.g. it's not possible to read class and method name from a properties file and then use Java 8 mechanisms to safely create an instance and call a particular method.
Consumer and Supplier are functional interfaces and they do not refer to reflection.
It's different things.
So i heard in the java 8, reflection pattern is deprecate and instead that we can use consumer and supplier.
Wrong information.
Related
I am learning about Java Lambdas and I asked myself is it always required to call a abstract method of functional interface if I want to use the lambda here?
#FunctionalInterface
public interface A {
public void somefunction();
}
#FunctionalInterface
public interface B extends A {
}
public class testing {
public static void main(String[] args) {
B b = () -> System.out.println("MyText");
b.somefunction(); //Why do I need to call somefunction()
}
}
If I don't write b.somefunction(); I don't get any output even though the compiler does not give an error.
I don't pass any value to the method so why do I need to call the abstract method?
Is there anyway to skip the abstract method call? If my case was to add or perform some calculations, then I can understand that I need to pass some values in method, but in the above scenario I am just printing the value.
If you want the output to print when your program runs, write:
public class testing {
public static void main(String[] args) {
System.out.println("MyText");
}
}
If you want the output to print when some other function runs, then you might use a lambda:
class Testing {
public static void main(String[] args) {
runn(() -> System.out.println("MyText"), 10);
}
static runn(Runnable task, int times) {
for (int i = 0; i < times; ++i) {
task.run();
}
}
}
Lambdas exist to make it easy to specify a function whose execution you want to delegate to another entity. When the lambda is invoked, its arguments, and the treatment of its result are up to someone else.
A functional interface serves to provide a way
to define what is to be performed on a given call and
to define when it is to be called.
Normally, you'd define a "lambda object" as you did and then pass it to somewhere else to tell what to do under a certain circumstance. If you want to see it this way, it is a kind of callback.
The entity where you pass this object calls/uses it when it sees time to do so, or you do it yourself, as you do it in your example.
I have created a simple interface using java8. In that it contains one method and one default method.
interface Lambda{
default void dummy(){
System.out.println("Call this..");
}
void yummy();
}
I'm trying to us these two methods using the historical way like
public class DefaultCheck {
public static void main(String[] args) {
DefaultCheck check = new DefaultCheck();
check.activate(new Lambda() {
#Override
public void yummy() {
dummy();
}
});
}
void activate(Lambda lambda){
lambda.yummy();
}
}
Now i'm trying to implement the same thing using lambda expression, getting error like `dummy is undefined`
check.activate(() -> {
dummy();
});
Can any one please suggest, how to implement this scenario using Lambda expression ??
It can't be done.
JLS 15.27.2 addresses this:
Unlike code appearing in anonymous class declarations, the meaning of
names and the this and super keywords appearing in a lambda body,
along with the accessibility of referenced declarations, are the same
as in the surrounding context (except that lambda parameters introduce
new names).
The transparency of this (both explicit and implicit) in the body of a
lambda expression - that is, treating it the same as in the
surrounding context - allows more flexibility for implementations, and
prevents the meaning of unqualified names in the body from being
dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to
talk about itself (either to call itself recursively or to invoke its
other methods), while it is more common to want to use names to refer
to things in the enclosing class that would otherwise be shadowed
(this, toString()). If it is necessary for a lambda expression to
refer to itself (as if via this), a method reference or an anonymous
inner class should be used instead.
The inner class implementation works since the code is called as if you coded:
check.activate(new Lambda() {
#Override
public void yummy() {
this.dummy();
}
});
Our problem now is that lambdas do not introduce a new scope. So, if you want your lambda to be able to reference itself, you may refine your #FunctionalInterface so that its functional method accepts itself and its required parameters:
check.activate(this_ -> this_.dummy());
where Lambda is defined as:
#FunctionalInterface
public interface Lambda {
void yummy(Lambda this_);
default void yummy() {
yummy(this);
}
default void dummy(){
System.out.println("Call this..");
}
}
If I understand it correctly. You are trying to call a default method in an interface through lambda implementation. I think it can be done.
#FunctionalInterface
interface Value
{
String init(Value a);
default String add(String b)
{
return "added content "+b;
}
default String getResult()
{
String c = init(this);
return c;
}
}
public class Main
{
public static void main(String[] args)
{
Value v = a -> a.add("inpout"); // here I am calling add method in Value interface.
String c = v.getResult();
System.out.println(c);
}
}
I would like to check, from an instance method of a non-final class, whether the constructors and initializers of that class and its chain of subclasses for the specific instance have already completed.
In the following example, I have a class Abstract, which can be used to implement an interface which allows listeners to be added (which, for simplicity, are just Runnable instances here) and which provides a method signalEvent() which calls all attached listeners.
abstract class Abstract {
protected final void signalEvent() {
// Check that constructs have run and call listeners.
}
public final void addListener(Runnable runnable) {
...
}
}
class Concrete extends Abstract {
Concrete() {
// Should not call signalEvent() here.
}
void somethingHappened() {
// May call signalEvent() here.
}
}
Now it is possible to call signalEvent() from within the subclass constructor, but there is no way that a listener has already been added by that time and the event would just be lost. In our code-base, once in a while, someone adds such a call and I would like to be able to catch such calls as early as possible (using an assert statement or similar).
Is it possible to check whether an instance method is being called, directly or indirectly, from the subclass constructor or initializer of the current instance or, alternatively, is it possible to check whether all constructors for an instance have been completed?
In short, there is no elegant Java mechanism that allows you to do that, but you may consider using a factory pattern. Instead of creating instances directly using new keyword, you could create a factory class, that takes care of creating the actual instance and invokes an additional "post-create" method, that lets the instance know it's been completely created.
If you're using some dependency injection like spring, you get that out of the box, but if not, a solution could look something like this:
interface PostConstruct { // the classes need to implement that
void postConstruct();
}
public class InstanceFactory {
public <T extends PostConstruct> T create(Class<T> clazz, Object... params) {
T instance = //create using reflection
instance.postConstruct();
return instance;
}
}
A solution to the problem to see if a method or code is being called from a constructor. The code below will print true and false respectivly but would be slow and not pretty at all.
I still believe it is not the right solution for the problem above. As Codbender said, better to check if a listener has been added or set a status variable which would be faster
Edit - fixed the issue that Codebender mentioned and also made sure to check back in the stack trace incase of being called a couple of methods deep
public class TestClass extends TestAbstract {
public TestClass() throws Exception {
submethod();
}
public void submethod() throws Exception {
System.out.println(isInConstructor());
}
public static void main(String[] args) throws Exception {
System.out.println(new TestClass().isInConstructor());
}
}
public class TestAbstract {
public boolean isInConstructor() throws Exception {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement element : elements) {
if (element.getMethodName().equals("<init>") &&
TestAbstract.class.isAssignableFrom(Class.forName(element.getClassName()))) {
return true;
}
}
return false;
}
}
I have created a simple interface using java8. In that it contains one method and one default method.
interface Lambda{
default void dummy(){
System.out.println("Call this..");
}
void yummy();
}
I'm trying to us these two methods using the historical way like
public class DefaultCheck {
public static void main(String[] args) {
DefaultCheck check = new DefaultCheck();
check.activate(new Lambda() {
#Override
public void yummy() {
dummy();
}
});
}
void activate(Lambda lambda){
lambda.yummy();
}
}
Now i'm trying to implement the same thing using lambda expression, getting error like `dummy is undefined`
check.activate(() -> {
dummy();
});
Can any one please suggest, how to implement this scenario using Lambda expression ??
It can't be done.
JLS 15.27.2 addresses this:
Unlike code appearing in anonymous class declarations, the meaning of
names and the this and super keywords appearing in a lambda body,
along with the accessibility of referenced declarations, are the same
as in the surrounding context (except that lambda parameters introduce
new names).
The transparency of this (both explicit and implicit) in the body of a
lambda expression - that is, treating it the same as in the
surrounding context - allows more flexibility for implementations, and
prevents the meaning of unqualified names in the body from being
dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to
talk about itself (either to call itself recursively or to invoke its
other methods), while it is more common to want to use names to refer
to things in the enclosing class that would otherwise be shadowed
(this, toString()). If it is necessary for a lambda expression to
refer to itself (as if via this), a method reference or an anonymous
inner class should be used instead.
The inner class implementation works since the code is called as if you coded:
check.activate(new Lambda() {
#Override
public void yummy() {
this.dummy();
}
});
Our problem now is that lambdas do not introduce a new scope. So, if you want your lambda to be able to reference itself, you may refine your #FunctionalInterface so that its functional method accepts itself and its required parameters:
check.activate(this_ -> this_.dummy());
where Lambda is defined as:
#FunctionalInterface
public interface Lambda {
void yummy(Lambda this_);
default void yummy() {
yummy(this);
}
default void dummy(){
System.out.println("Call this..");
}
}
If I understand it correctly. You are trying to call a default method in an interface through lambda implementation. I think it can be done.
#FunctionalInterface
interface Value
{
String init(Value a);
default String add(String b)
{
return "added content "+b;
}
default String getResult()
{
String c = init(this);
return c;
}
}
public class Main
{
public static void main(String[] args)
{
Value v = a -> a.add("inpout"); // here I am calling add method in Value interface.
String c = v.getResult();
System.out.println(c);
}
}
For example I have the following method call:
Requests.sendGet("/type", Model.setTypes);
Model.setTypes is a setter for a List of Types, I want the sendGet method to be able to call whatever method gets passed into it, and no the sendGet method can't just call Model.setTypes itself, because it depends on what type of Get request is being performed.
Thanks to anyone who replies.
Use the command pattern.
public interface Command {
public void execute();
}
public class Requests {
public static void sendGet(String url, Command command) {
// Do your stuff here and then execute the command.
command.execute();
}
}
final Model model = getItSomehow(); // Must be declared final.
Requests.sendGet("/type", new Command() {
public void execute() {
model.setType();
}
});
You can if necessary add an argument to execute() method, like RequestEvent which can be created by Requests#sendGet() and accessed in Command#execute().
It is possible, although clumsy: You can use java.lang.reflect.Method to point to a method and call its invoke member to call it.
However, in almost all cases, this is not what you want to do. Instead, use an interface for that (i.e. your function accepts an object of a certain type that implements an interface), or you can take a Runnable and call the run() function of it, or a Callable and use call().
(Thanks to Crom for pointing out Callable)
Java does not have first class functions: that is functions - amongst other things - passable as arguments - albeit there is a proposal. Instead this problem is typically solved in Java with function objects - usually objects that implement an interface with a single function. An example would be the Collections API Comparator.
So in your situation define an interface (e.g. ModelSetter) with a single method (e.g. setTypes(List list)). Define Request.sentGet(ModelSetter modelSetter).
public void invokeAMethod(Object o, String methodName, String...params){
try{
Class<?> driverClass = o.getClass();
Method[] driverMethod = driverClass.getMethods();
for(Method m : driverMethod) {
if(m.getName().equalsIgnoreCase(methodName)) {
if(m.isVarArgs()) {
Object[] obj = new Object[params.length];
for(int i=0;i<params.length;i++) {
obj[i] = params[i];
}
m.invoke(new Object[]{obj});
}
else
m.invoke(o,params);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
In The above code, parameters are:
Object o: Object of the class in which your calling method belongs
String methodName: name of the method which you want to call.
String...params: parameters of the method which you want to call.
public class Sample{
public static void main(String[] args){
method2("method1")
}
public void method1(){
System.out.println("method1");
}
public static void method2(String methodName){
invokeAMethod(this,method1);
}
}