java cast and call a string as method on an object - java

I am using AOP to find the value of an instance variable before its going to be set and after it is set. So I am intercepting all setxxx methods and trying to do a getxxx before and after.
//actual instance
Object target = joinPoint.getTarget();
//Type of the instance
Class objectClass = target.getClass();
I want to call a string "getFirstName()" that is actually a method name on the actual instance (target). How can I do so
right now I can do the following
if (target instanceof User) {
instanceVarCurrentValue = ((User) target).getFirstName();
}
But i cannot check for instance of for all objects in my project and for each class I will have to check all properties

You need to use Reflection. You must find the method on class and invoke it.
Please see the below code:
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
User user = new User();
String name = runMethod(user, "getFirstName");
System.out.println(name);
}
private static String runMethod(Object instance, String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = instance.getClass().getMethod(methodName);
return (String)method.invoke(instance);
}

The possible ways to solve this in Java is to write code that covers all cases with lots of if and else and instanceof expressions.
You will need to implement something like ObjectConverter as in this answer,
Or you can always use Java Reflection API.

My go-to solution for things like this is a handy library called jOOR - for 'Java Object Oriented Reflection'. It's a fluent wrapper around Java's reflection tools, which lets you write code like so:
String firstName = on(target).call("getFirstName").get();
With the above, ANY object 'target' with a method called getFirstName will work here, and the get() will (try to) cast the result as a string. Pretty handy if you know you only have to deal with a specific set of types that are guaranteed to have the methods you're interested in, but don't want to write and maintain an enormous if-else block.

Related

Get values of static fields with reflection [duplicate]

Say I have a class:
public class R {
public static final int _1st = 0x334455;
}
How can I get the value of the "_1st" via reflection?
First retrieve the field property of the class, then you can retrieve the value. If you know the type you can use one of the get methods with null (for static fields only, in fact with a static field the argument passed to the get method is ignored entirely). Otherwise you can use getType and write an appropriate switch as below:
Field f = R.class.getField("_1st");
Class<?> t = f.getType();
if(t == int.class){
System.out.println(f.getInt(null));
}else if(t == double.class){
System.out.println(f.getDouble(null));
}...
R.class.getField("_1st").get(null);
Exception handling is left as an exercise for the reader.
Basically you get the field like any other via reflection, but when you call the get method you pass in a null since there is no instance to act on.
This works for all static fields, regardless of their being final. If the field is not public, you need to call setAccessible(true) on it first, and of course the SecurityManager has to allow all of this.
I was following the same route (looking through the generated R class) and then I had this awful feeling it was probably a function in the Resources class. I was right.
Found this:
Resources::getIdentifier
Thought it might save people some time. Although they say its discouraged in the docs, which is not too surprising.
I was looking for how to get a private static field and landed here.
For fellow searchers, here is how:
public class R {
private static final int _1st = 0x334455;
}
class ReflectionHacking {
public static main(String[] args) {
Field field = R.class.getFieldDeclaration("_1st");
field.setAccessible(true);
int privateHidenInt = (Integer)field.get(null);
}
}

Creating objects from strings

So I've read in some data from an XML:
String arg1Value;
String arg2Value;
String arg2TypeAsString;
String arg1TypeAsString;
and I want to create an object: ObjectType(arg1Type, arg2Type);
I'm trying this:
(ObjectType) Class.forName(arg1TypeAsString).getConstructor(arg1Type.class, arg2Type.class).newInstance(arg1Value, arg2Value)
But this gives me a noSuchMethodException: ObjectType.<init>(arg1Type, arg2Type)
Note that I'm trying to create different objects but they all extend from ObjectType and all their arguments extend from arg1Type and arg2Type respectively.
Given the specifications are a bit vague (no actual code), try the followings:
Make sure your constructor does not have private, protected or default package modifier, if so, use getDeclaredConstructor() instead
Define a default constructor for ObjectType class
Split your statement on multiple lines:
Class<ObjectType> otClass = (ObjectType) class.forName(arg1TypeAsString);
Constructor<ObjectType> otConstructor = otClass.getConstructor(arg1Type.class, arg2Type.class);
ObjectType ot = otConstructor.newInstance(arg1Value, arg2Value);
My initial assumption was that newInstance should be called with array of objects. This is not correct, see comment below. Then likely reason is that you are passing primitive type to newInstance for example int instead of Integer. Naturally creating array of Objects will eliminate such possibility. Finally I managed to replicate error message by removing constructor from my target class so it couldn't be found
java.lang.NoSuchMethodException: Foo.<init>(java.lang.String, java.lang.String)
Please take a look at all those exceptions which implementation throws. Please create your ObjectType compile it and place it in classpath so it could be found.
Here is my implementation of method returning Object which you can cast to desired type
static Object createInstance(String clsName, String ctorType1, String ctorVal1, String ctorType2, String ctorVal2)
throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
return Class.forName(clsName).getConstructor(Class.forName(ctorType1), Class.forName(ctorType2))
.newInstance(new Object[]{ctorVal1, ctorVal2});
}
It is tested and works. Quite few exceptions to catch. You may want to adjust parameter types so they fit your design requirements. This is my test class
public class Foo {
public Foo(String in, String out){}
}

Why is Eclipse suggesting I make my method static

I am calling a method from a class and it gives me an error to make the method static. I am confused about why, as I asked this question What's the difference between a class variable and a parameter in a constructor? and my understanding was that class variables were made static.
Patient class:
public String setOption(String option) throws IOException
{
option = stdin.readLine();
//stuff here
return option;
}
Patient management system:
public class PatientManagementSystem
{
static BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in));
public static void main(String[] args) throws IOException
{
Patient.setOption(null);
}
}
The error:
Do I change the method to static or create a local variable?
Based on your earlier question, I think may not be fully digging the concept of the local variable. In this method:
public String setOption(String option) throws IOException
{
option = stdin.readLine();
return option;
}
option is a local variable. You pass the initial value for that variable as an argument to the setOption method each time you call it (and you happen to ignore that value), but with that detail out of the way, this is the same as
public String setOption() throws Exception
{
String option = stdin.readLine();
return option;
}
Now, local variables are something completely different from instance or class variables: they are valid only within a method body, and exist only during the time that method is executing. With that in mind, let's look at this code:
static BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in));
public static void main(String[] args) throws IOException
{
Patient.setOption(null);
}
Here you are basically misusing a class variable stdin for something which should have been a local variable:
public static void main(String[] args) throws IOException
{
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
Patient.setOption(null);
}
On to the question of your method call... setOption is currently an instance method, which means it must be called in the context of an instance. You are calling it as-is, with no instances of Patient involved. If you continue down this road, you won't be able to represent more than a single patient, probably not your idea. So you want to keep the method as it is and create an instance of Patient:
Patient p = new Patient();
p.setOption(...);
In your overall design it is not clear what role setOption should play, but it is not a good idea that it uses the static stdin variable (I already made it local above). You want to pass any data read from stdin into the setOption method and thus decouple it from the input reading logic.
You (probably) need to create an object of the Patient class.
Patient myPatient = new Patient();
myPatient.setOption(null);
It's hard to necessarily know what you want to do with such limited information. I don't know what you intend to do with the Patient class, but my best guess? It makes sense to do it this way, given you're trying to call a method with a setter naming convention.
If you don't intend to instantiate an object and go the route of making setOption a static method, then you should probably change the method name.
With a more in-depth explanation of what exactly you're trying to accomplish (not even talking pseudo-code, just a very abstract idea of what you're trying to do), it would be easier to explain more about static here (with your specific example) and what you should be doing, etc.
Do I change the method to static or create a local variable?
Both is OK.
If your method doesn't use class variables, it's better to make it static, so you do not have to instantiate the class for the method call.
The question of when to make something static vs. non-static is based on the real-world object/concept being modeled. Let's take the example of the Patient object in this code. Without seeing any code about the Patient, it's still pretty clear what a Patient is and what it represents. So, at its simplest:
If you're doing something with a particular Patient (let's say Jane Doe), then it's not static. It's operating on an instance of a Patient.
If you're doing something regarding the concept of a Patient, then it's static.
So some non-static operations might be:
Update the Patient's name
Admit/discharge the Patient from a hospital
Transfer the Patient to a different Doctor
All of these would involve a specific Patient, which would have been initialized somewhere:
var janeDoe = new Patient("Jane Doe");
// ...
janeDoe.TransferTo(doctorSmith);
I'm actually having trouble thinking of some static methods for a Patient. The most common example of a static method is probably a factory method, where you get an existing Patient or collection of Patients. Something like:
var janeDoe = Patient.Fetch("Jane Doe");
or:
var todaysPatients = Patient.Fetch(DateTime.Today);
Various helper methods are often static as well, perhaps a method on the Patient object which accepts a MedicalRecord object and converts it to a different format, for example.
But the overall idea is the same. If you're interacting with a specific instance of an object, then you need an instance of that object to represent that real-world concept.
Because you are directly calling that method without creating object of class.
When to have static methods?
To call a method in a static way, you have to make it static :
public static String setOption(String option) throws IOException
But in your example if stdin is not a static member of your Patient class, it can't work.
To sum up, you can call a method the way you call it when it's declared static. In a static method you can access only static members of your class.
Try this in your main method :
Patient myPatient = new Patient();
myPatient.setOption(null);
We create classes with static methods when we intend to use those methods as utility methods, like parseInt in the class Integer. thus either modify the method
public static String setOption(String option) throws IOException // STATIC
{
option = stdin.readLine();
//stuff here
return option;
}
and then use the method like
Patient.setOption(null);
OR instantiate an object for Patient like
Patient obj = new Patient();
obj.setOption(null);
In Java main method is special. It's the starting point of your code. Static methods could be called from anywhere in your code. Thus actually it does not belong to the containing class. It's also true for the main method.
Thus you should construct your object in the main method and then use the constructed instance's methods. If you do not construct your an instance, then your ide will recognise the error and suggest you to make it static.

Reflection in java?

I am newbie to java programming language.
My problem is:
I want to read sys.input for a class name from console. Upon reading the name of the class, I want to generate that class automatically and call its method if that class exists already.
my trial is here. Although I dont get any error, nothing happens.
my kind regards.
class s1{
public s1(){
System.out.println(""+ s1.class);
}
}
public class reflection {
public static void main(String[] args) throws IOException, ClassNotFoundException{
System.out.println("enter the class name : ");
BufferedReader reader= new BufferedReader(new InputStreamReader(System.in));
String line = "reflection_N3.";
line+=reader.readLine();
//System.out.println(line);
// "name" is the class name to load
Class clas = Class.forName(line);
clas.getClassLoader();
}
}
You are not creating an instance of the class. Try
Class clas = Class.forName(line);
Object obj = clas.newInstance();
However, the problem is, you can't do much with this object unless you know its exact type, and cast it to that type.
In this example, you could try casting it to your class type, e.g.
if (obj instanceof s1) {
s1 myS1 = (s1) obj;
myS1.s1();
}
However, this hardly works in real life, where you don't know the possible types in advance. The typical solution to this is to define an interface for a specific purpose, and require that the class implements that interface. Then you can downcast the class instance to that interface (throwing an exception if the cast fails), and call its interface methods, without needing to know its concrete type.
Or, as #helios noted, you can use reflection to obtain a method of the loaded class having a specific name.
Btw the Java convention is to start class names with uppercase, hence S1 and Reflection.
You're only obtaining the ClassLoader, you're never actually constructing an object of the specified class.
Use clas.newInstance() if you want to call the default constructor, or investigate Class.getConstructor(...) if you need to call a specific constructor.

java: How can I do dynamic casting of a variable from one type to another?

I would like to do dynamic casting for a Java variable, the casting type is stored in a different variable.
This is the regular casting:
String a = (String) 5;
This is what I want:
String theType = 'String';
String a = (theType) 5;
Is this possible, and if so how? Thanks!
Update
I'm trying to populate a class with a HashMap that I received.
This is the constructor:
public ConnectParams(HashMap<String,Object> obj) {
for (Map.Entry<String, Object> entry : obj.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
The problem here is that some of the class' variables are of type Double, and if the number 3 is received it sees it as Integer and I have type problem.
Yes it is possible using Reflection
Object something = "something";
String theType = "java.lang.String";
Class<?> theClass = Class.forName(theType);
Object obj = theClass.cast(something);
but that doesn't make much sense since the resulting object must be saved in a variable of Object type. If you need the variable be of a given class, you can just cast to that class.
If you want to obtain a given class, Number for example:
Object something = new Integer(123);
String theType = "java.lang.Number";
Class<? extends Number> theClass = Class.forName(theType).asSubclass(Number.class);
Number obj = theClass.cast(something);
but there is still no point doing it so, you could just cast to Number.
Casting of an object does NOT change anything; it is just the way the compiler treats it.
The only reason to do something like that is to check if the object is an instance of the given class or of any subclass of it, but that would be better done using instanceof or Class.isInstance().
Update
according your last update the real problem is that you have an Integer in your HashMap that should be assigned to a Double. What you can do in this case, is check the type of the field and use the xxxValue() methods of Number
...
Field f = this.getClass().getField(entry.getKey());
Object value = entry.getValue();
if (Integer.class.isAssignableFrom(f.getType())) {
value = Integer.valueOf(((Number) entry.getValue()).intValue());
} else if (Double.class.isAssignableFrom(f.getType())) {
value = Double.valueOf(((Number) entry.getValue()).doubleValue());
} // other cases as needed (Long, Float, ...)
f.set(this, value);
...
(not sure if I like the idea of having the wrong type in the Map)
You'll need to write sort of ObjectConverter for this. This is doable if you have both the object which you want to convert and you know the target class to which you'd like to convert to. In this particular case you can get the target class by Field#getDeclaringClass().
You can find here an example of such an ObjectConverter. It should give you the base idea. If you want more conversion possibilities, just add more methods to it with the desired argument and return type.
Regarding your update, the only way to solve this in Java is to write code that covers all cases with lots of if and else and instanceof expressions. What you attempt to do looks as if are used to program with dynamic languages. In static languages, what you attempt to do is almost impossible and one would probably choose a totally different approach for what you attempt to do. Static languages are just not as flexible as dynamic ones :)
Good examples of Java best practice are the answer by BalusC (ie ObjectConverter) and the answer by Andreas_D (ie Adapter) below.
That does not make sense, in
String a = (theType) 5;
the type of a is statically bound to be String so it does not make any sense to have a dynamic cast to this static type.
PS: The first line of your example could be written as Class<String> stringClass = String.class; but still, you cannot use stringClass to cast variables.
You can do this using the Class.cast() method, which dynamically casts the supplied parameter to the type of the class instance you have. To get the class instance of a particular field, you use the getType() method on the field in question. I've given an example below, but note that it omits all error handling and shouldn't be used unmodified.
public class Test {
public String var1;
public Integer var2;
}
public class Main {
public static void main(String[] args) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("var1", "test");
map.put("var2", 1);
Test t = new Test();
for (Map.Entry<String, Object> entry : map.entrySet()) {
Field f = Test.class.getField(entry.getKey());
f.set(t, f.getType().cast(entry.getValue()));
}
System.out.println(t.var1);
System.out.println(t.var2);
}
}
You can write a simple castMethod like the one below.
private <T> T castObject(Class<T> clazz, Object object) {
return (T) object;
}
In your method you should be using it like
public ConnectParams(HashMap<String,Object> object) {
for (Map.Entry<String, Object> entry : object.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, castObject(entry.getValue().getClass(), entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
It works and there's even a common pattern for your approach: the Adapter pattern. But of course, (1) it does not work for casting java primitives to objects and (2) the class has to be adaptable (usually by implementing a custom interface).
With this pattern you could do something like:
Wolf bigBadWolf = new Wolf();
Sheep sheep = (Sheep) bigBadWolf.getAdapter(Sheep.class);
and the getAdapter method in Wolf class:
public Object getAdapter(Class clazz) {
if (clazz.equals(Sheep.class)) {
// return a Sheep implementation
return getWolfDressedAsSheep(this);
}
if (clazz.equals(String.class)) {
// return a String
return this.getName();
}
return null; // not adaptable
}
For you special idea - that is impossible. You can't use a String value for casting.
Your problem is not the lack of "dynamic casting". Casting Integer to Double isn't possible at all. You seem to want to give Java an object of one type, a field of a possibly incompatible type, and have it somehow automatically figure out how to convert between the types.
This kind of thing is anathema to a strongly typed language like Java, and IMO for very good reasons.
What are you actually trying to do? All that use of reflection looks pretty fishy.
Don't do this. Just have a properly parameterized constructor instead. The set and types of the connection parameters are fixed anyway, so there is no point in doing this all dynamically.
For what it is worth, most scripting languages (like Perl) and non-static compile-time languages (like Pick) support automatic run-time dynamic String to (relatively arbitrary) object conversions. This CAN be accomplished in Java as well without losing type-safety and the good stuff statically-typed languages provide WITHOUT the nasty side-effects of some of the other languages that do evil things with dynamic casting. A Perl example that does some questionable math:
print ++($foo = '99'); # prints '100'
print ++($foo = 'a0'); # prints 'a1'
In Java, this is better accomplished (IMHO) by using a method I call "cross-casting".
With cross-casting, reflection is used in a lazy-loaded cache of constructors and methods that are dynamically discovered via the following static method:
Object fromString (String value, Class targetClass)
Unfortunately, no built-in Java methods such as Class.cast() will do this for String to BigDecimal or String to Integer or any other conversion where there is no supporting class hierarchy. For my part, the point is to provide a fully dynamic way to achieve this - for which I don't think the prior reference is the right approach - having to code every conversion. Simply put, the implementation is just to cast-from-string if it is legal/possible.
So the solution is simple reflection looking for public Members of either:
STRING_CLASS_ARRAY = (new Class[] {String.class});
a) Member member = targetClass.getMethod(method.getName(),STRING_CLASS_ARRAY);
b) Member member = targetClass.getConstructor(STRING_CLASS_ARRAY);
You will find that all of the primitives (Integer, Long, etc) and all of the basics (BigInteger, BigDecimal, etc) and even java.regex.Pattern are all covered via this approach. I have used this with significant success on production projects where there are a huge amount of arbitrary String value inputs where some more strict checking was needed. In this approach, if there is no method or when the method is invoked an exception is thrown (because it is an illegal value such as a non-numeric input to a BigDecimal or illegal RegEx for a Pattern), that provides the checking specific to the target class inherent logic.
There are some downsides to this:
1) You need to understand reflection well (this is a little complicated and not for novices).
2) Some of the Java classes and indeed 3rd-party libraries are (surprise) not coded properly. That is, there are methods that take a single string argument as input and return an instance of the target class but it isn't what you think... Consider the Integer class:
static Integer getInteger(String nm)
Determines the integer value of the system property with the specified name.
The above method really has nothing to do with Integers as objects wrapping primitives ints.
Reflection will find this as a possible candidate for creating an Integer from a String incorrectly versus the decode, valueof and constructor Members - which are all suitable for most arbitrary String conversions where you really don't have control over your input data but just want to know if it is possible an Integer.
To remedy the above, looking for methods that throw Exceptions is a good start because invalid input values that create instances of such objects should throw an Exception. Unfortunately, implementations vary as to whether the Exceptions are declared as checked or not. Integer.valueOf(String) throws a checked NumberFormatException for example, but Pattern.compile() exceptions are not found during reflection lookups. Again, not a failing of this dynamic "cross-casting" approach I think so much as a very non-standard implementation for exception declarations in object creation methods.
If anyone would like more details on how the above was implemented, let me know but I think this solution is much more flexible/extensible and with less code without losing the good parts of type-safety. Of course it is always best to "know thy data" but as many of us find, we are sometimes only recipients of unmanaged content and have to do the best we can to use it properly.
Cheers.
So, this is an old post, however I think I can contribute something to it.
You can always do something like this:
package com.dyna.test;
import java.io.File;
import java.lang.reflect.Constructor;
public class DynamicClass{
#SuppressWarnings("unchecked")
public Object castDynamicClass(String className, String value){
Class<?> dynamicClass;
try
{
//We get the actual .class object associated with the specified name
dynamicClass = Class.forName(className);
/* We get the constructor that received only
a String as a parameter, since the value to be used is a String, but we could
easily change this to be "dynamic" as well, getting the Constructor signature from
the same datasource we get the values from */
Constructor<?> cons =
(Constructor<?>) dynamicClass.getConstructor(new Class<?>[]{String.class});
/*We generate our object, without knowing until runtime
what type it will be, and we place it in an Object as
any Java object extends the Object class) */
Object object = (Object) cons.newInstance(new Object[]{value});
return object;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
DynamicClass dynaClass = new DynamicClass();
/*
We specify the type of class that should be used to represent
the value "3.0", in this case a Double. Both these parameters
you can get from a file, or a network stream for example. */
System.out.println(dynaClass.castDynamicClass("java.lang.Double", "3.0"));
/*
We specify a different value and type, and it will work as
expected, printing 3.0 in the above case and the test path in the one below, as the Double.toString() and
File.toString() would do. */
System.out.println(dynaClass.castDynamicClass("java.io.File", "C:\\testpath"));
}
Of course, this is not really dynamic casting, as in other languages (Python for example), because java is a statically typed lang. However, this can solve some fringe cases where you actually need to load some data in different ways, depending on some identifier. Also, the part where you get a constructor with a String parameter could be probably made more flexible, by having that parameter passed from the same data source. I.e. from a file, you get the constructor signature you want to use, and the list of values to be used, that way you pair up, say, the first parameter is a String, with the first object, casting it as a String, next object is an Integer, etc, but somehwere along the execution of your program, you get now a File object first, then a Double, etc.
In this way, you can account for those cases, and make a somewhat "dynamic" casting on-the-fly.
Hope this helps anyone as this keeps turning up in Google searches.
Try this for Dynamic Casting. It will work!!!
String something = "1234";
String theType = "java.lang.Integer";
Class<?> theClass = Class.forName(theType);
Constructor<?> cons = theClass.getConstructor(String.class);
Object ob = cons.newInstance(something);
System.out.println(ob.equals(1234));
I recently felt like I had to do this too, but then found another way which possibly makes my code look neater, and uses better OOP.
I have many sibling classes that each implement a certain method doSomething(). In order to access that method, I would have to have an instance of that class first, but I created a superclass for all my sibling classes and now I can access the method from the superclass.
Below I show two ways alternative ways to "dynamic casting".
// Method 1.
mFragment = getFragmentManager().findFragmentByTag(MyHelper.getName(mUnitNum));
switch (mUnitNum) {
case 0:
((MyFragment0) mFragment).sortNames(sortOptionNum);
break;
case 1:
((MyFragment1) mFragment).sortNames(sortOptionNum);
break;
case 2:
((MyFragment2) mFragment).sortNames(sortOptionNum);
break;
}
and my currently used method,
// Method 2.
mSuperFragment = (MySuperFragment) getFragmentManager().findFragmentByTag(MyHelper.getName(mUnitNum));
mSuperFragment.sortNames(sortOptionNum);
Just thought I would post something that I found quite useful and could be possible for someone who experiences similar needs.
The following method was a method I wrote for my JavaFX application to avoid having to cast and also avoid writing if object x instance of object b statements every time the controller was returned.
public <U> Optional<U> getController(Class<U> castKlazz){
try {
return Optional.of(fxmlLoader.<U>getController());
}catch (Exception e){
e.printStackTrace();
}
return Optional.empty();
}
The method declaration for obtaining the controller was
public <T> T getController()
By using type U passed into my method via the class object, it could be forwarded to the method get controller to tell it what type of object to return. An optional object is returned in case the wrong class is supplied and an exception occurs in which case an empty optional will be returned which we can check for.
This is what the final call to the method looked like (if present of the optional object returned takes a Consumer
getController(LoadController.class).ifPresent(controller->controller.onNotifyComplete());

Categories