Reflection on Enums - java

One of the methods I am currently writing for my Java library takes an array of an arbitrary enumeration type as its sole argument. If any of these is non-null, I can access the instance of java.lang.Class representing that enumeration type, which may or may not be a public type. (If they are all null, there is no purpose to this anyway under the circumstances.) How do I get the number of possible values that enumeration type has? The approach I am currently using - Array.getLength(clazz.getMethod("values").invoke(null)); - fails when the Enum class is not public. How do I fix this?

The easiest way to get an array of enum constants from a Class object is
clazz.getEnumConstants();
To find the number of enum constants you can add .length to this.
If you want to get the array of enum constants from an instance of an enum, it is important to do
e.getDeclaringClass().getEnumConstants();
rather than
e.getClass().getEnumConstants();
The reason for this is demonstrated by the following example:
private enum Colour {
WHITE,
BLUE {
#Override
public String toString() {
return "blue";
}
}
}
public static void main(String[] args) throws Exception {
System.out.println(Arrays.toString(Colour.BLUE.getClass().getEnumConstants()));
System.out.println(Arrays.toString(Colour.WHITE.getClass().getEnumConstants()));
System.out.println(Arrays.toString(Colour.BLUE.getDeclaringClass().getEnumConstants()));
}
This program outputs
null
[WHITE, blue]
[WHITE, blue]
What is going on here is that in order to override the method toString for the BLUE constant, a subclass of Colour is created. This means that Colour.BLUE.getClass() does not return Colour.class, so Colour.BLUE.getClass().getEnumConstants() returns null. This issue does not apply for WHITE because WHITE does not require an extra class.

Related

Do arraylist needs to be specified as return type in method after modification?

I would like to know what is the best practice to return 'updated' ArrayList?
For example, if I am adding in a new element, it seems that whether if I did or did not specify the return type (see the addNewA() and addNewB()), the ArrayList in my main() method will still be 'updated' nonetheless.
Should I or should I not specify the return type?
Currently in my client program, most of the methods, I have specified it as void (no return type) and while the overall program still does works as intended, thought I would like to get this clarified and make the necessary changes if necessary.
public class MyClient
{
public static ArrayList<Person> addNewA(ArrayList<Person> myArray)
{
Person jack = new Person("jack", 24);
myArray.add(jack);
return myArray;
}
public static void addNewB(ArrayList<Person> myArray)
{
Person ben= new Person("ben", 19);
myArray.add(ben);
}
public static void main(String[] args)
{
ArrayList<Person> personArray= new ArrayList();
addNewA(personArray); // will return me an array size of 1
addNewB(personArray); // will return me an array size of 2
}
}
In a case like this, you should not return the list and should make your method void.
Different languages have different conventions, but one of Java's is that methods that operate by modifying their arguments (or the object they're called on) should not return values. Returning a value implies to someone using your code that a different object is being returned, since otherwise there is no use in returning an object the caller already has1. A method that is void, on the other hand, couldn't possibly be returning a copied-and-extended list, so it's very clear that it's intended to operate by modifying the list that you give it in the first place.
(By the way, you should also just use List<Person>, and you should pay attention to the warning you get about using new ArrayList() instead of new ArrayList<>().)
1 There is a specific exception to this, called the fluent builder pattern, but it's not easily confused with general code like this.
In java (and most high level strict type languages) Objects are passed by reference and primitives passed by value.
When using the new keyword you create an object.
While primitives (like int, char, double ect) are passed by value (meaning that a copy of the value of the variable will be sent to the invoked function), Object types are passed by reference, meaning that the actual original object is passed to the function.
To sum up - since you are using object here (ArrayList), you don't need a return type since the original object is changing.

Is it necessary to have toString() in an enum in Java?

I don't think we can instantiate an Enum. So do we need to have toString(), equals() and hashCode() method for an enum? Is this statement true?
Also as a follow up question
What does "this" keyword refers to in the following enum class?
public enum DocuType {
text, print, html, pdf; //Why aren't these in caps?
public boolean isPrint() {return this == print; } //What does this refers to?
public boolean isText() {return this == text; }
public boolean isTextOrPrint() { return isText() || isPrint(); }
}
How do I call any of the boolean methods of this enum as they are not static?
Also when I call, what does the keyword "this" refers to ?
I don't think we can instantiate an Enum.
Enum is one of type as we have class type. The way we can create instance (i.e. create variable) of a class, similarly we can create variables of Enum but that's only during during its definition which eventually makes them a Constant.
So do we need to have toString(), equals() and hashCode() method for an enum?
equals() & hashcode() are used to compare two instances. In case of class instances, the instances are created dynamically. So this means we don't have knowledge about instances beforehand and hence we need to compare them to know if they are equal. However, in case of Enum we know the instances when we define the Enum. So, we know beforehand whether they are equal or not. If the enum instances mean to be equal why on the earth we need two separate equal enum instances. So, in case of enum we generally don't override these methods.
What does "this" keyword refers to in the following enum class?
&
How do I call any of the boolean methods of this enum as they are not static?
&
Also when I call, what does the keyword "this" refers to ?
this means an instance currently in access. In your example, you have DocuType instances as text, pdf, print, html. When you invoke a method on any of the instance, ex: DocuType.text.isPrint(), this keyword inside the isPrint method will point to text. So, for instance pdf, all the methods will return false except isPdf().
So do we need to have toString(), equals() and hashCode() method for an enum? Is this statement true?
You don't need any of these methods in the enum.
Also as a follow up question What does "this" keyword refers to in the following enum class?
Imagine you have this code:
DocuType myType = DocuType.print;
If you want to check if the document is a PRINT document, you can do this:
boolean isPrint = myType.isPrint();
In this case, this is the myType, which means that it's the print enum. In the end, the result is true, because print == print;
I would also suggest to read the Tutorial to Enums
It seems you lack the knowledge of the concept of an enum.
And to your last question, an enum is static, but each "type" of it is an object, meaning you can do
DocuType.html.isText(); // false
DocuType.print.isPrint(); // true
To initalize your own Enum you have to
DocuType TextDocu = DocuType.text;
And you can write them in CAPS, but you don't have to, but it's recommened.
To explain it more in detail:
enum DocuType //this is an enum and not instantiatable
text,print,html,pdf // these are Objects with the functions of the enum and are an instance
As preparation for an explanation, a quick glance back in history.
Before enums were available in Java, a possible replacement could have been constructed like that:
public class DocuType {
public final static DocuType text=new DocuType();
public final static DocuType print=new DocuType();
public final static DocuType html=new DocuType();
public final static DocuType pdf=new DocuType();
private DocuType(){}; // hide constructor
public boolean isPrint() {return this == print; }
public boolean isText() {return this == text; }
public boolean isTextOrPrint() { return isText() || isPrint(); }
}
As you can see, while you cannot create new instances of DocuType, 4 static instances of them are already prepared for you in the Class.
Javas enum work very similar to that example (less writing involved, obviously); therefore, this refers to the instance you execute the method on. Regarding toString, it's up to you; the default implementation can be good enough or not. There is no need to implement neither equals nor hashCode.

I need to understand behaviour of enum in java example?

The first one is enum class
enum coffeeSize{
BIG(8), HUGE(10), OVERWHELMING(16);
private int ounces;
coffeeSize(int ounces ){
this.ounces = ounces;
}
public int getOunces(){
return ounces;
}
}
This is class CoffeeTest1 and main
public class CoffeeTest1 {
coffeeSize size;
public static void main (String args[]) {
CoffeeTest1 drink1 = new CoffeeTest1();
drink1.size = coffeeSize.BIG;
System.out.println(" " + drink1.size.getOunces());
}
}
The below is output
8
My question :
I don't understand the how drink1.size.getounces() manage to output 8. I haven't given constructor coffeeSize(8) object (ex: coffeeSize somex = new coffeeSize(BIG)). I want to know this simple subtle logic behind. Can someone help me understand please?
I dont understand the how "drink1.size.getounces() " manage to output 8.
[...]
I want to know this simple subtle logic behind.
To understand the logic behind this, you can think of your enum as a regular class (which is actually how it is compiled), and
BIG(8)
as an instance of this class similar to
new coffeesize(8);
It should now be clear why drink1.size.getOunces() prints 8: BIG is just an instance of the coffeesize enum, for which you set ounces to 8 when constructing it.
One suggestion: find, learn, and follow the Sun Java coding standards. It'll improve your code's readability.
It outputs 8 because that's the size, in ounces, for BIG coffee size, according to your enum. That's the value that you passed into the BIG constructor.
drink1 is the instance of the class, which has a package visible data member of type coffeeSize named size. Every coffeeSize instance has a method getOunces that returns the integer value that you passed into its constructor.
There's nothing subtle about it.
You will notice the getOunces method is defined on the enum. Enum values can themselves have properties and methods, in Java.
It is implied that CoffeeTest1 has a field that references the enum value.
So drink1 is an instance of that class..
the size property is set to the BIG instance of the enum..
Big has ounces 8.
When you specifies BIG(8) you are creating it passing 8 to its constructor (10 or 16). When you use it coffeeSize.BIG.getOunces() you are invoking its method getOunces. BIG, HUGE and OVERWHELMING are the possible values for a coffeeSize, each one with its own state.
enum Colour {
Black,White,Red,Green,Yellow,Grey
}
public class EnumExample {
public static void main(String[] args) {
Colour colour;
colour = Colour.Black;
System.out.println("Selected "+colour+" Colour");
colour = Colour.Yellow;
System.out.println("Selected "+colour+" Colour");
}
}

abstract method of a set length array in java?

i am trying to create a abstract array method that specify's that this abstract object of an array can only hold 3 items.
Now i have tried doing something like this public abstract BaseAdapter[3] adapters(); but it complains with an error that it cant be done this way.
is their another way or do i need to just do public abstract BaseAdapter[] adapters();?
That will work fine but the sub class can still pass an array larger than 3 items
You could solve it like this:
Create an abstract helper method (which you can override) named createAdapters() with return type BaseAdapter[]
protected abstract BaseAdapter[] createAdapters();
In your super-class you have a final method adapters that does the following:
public final BaseAdapter[] adapters() {
BaseAdapter[] adapters = createAdapters();
if (adapters.length != 3)
throw new Exception("Error: Please return 3 adapters.");
return adapters;
}
Another alternative would be to create a simple class called BaseAdapterTriple (perhaps with a more descriptive name) containing the three BaseAdapters, and use that as return value.
As far as I'm aware there is no way to place restrictions like that on objects in a method signature. Either use exceptions in implementing methods, or use custom classes.
You seem to misunderstand the meaning of the abstract modifier in Java.
abstract applies to classes and methods, not to fields / variables, so what you are trying cannot work.
Please describe what you want to accomplish, then we can help :-).
See e.g. http://download.oracle.com/javase/tutorial/java/IandI/abstract.html for an explanation of abstract.
No, you can't do this neither with arrays nor lists. You can throw an exception if number exceeds 3 and document this behavior.
If you want an adapters() method which can only return 3 BaseAdapter at most and having subclasses to implement the "return" themselves while respecting the 3max contract, you should do the verification in your adapters() method, and invoke an abstract method.
For example :
abstract class YourAbstractClass{
public BaseAdapter[] adapters(){
BaseAdapter[] adapters = internalAdapters();
if(adapters.length > 3){
throw new IllegalStateException();
}
return adapters;
}
protected abstract BaseAdapter[] internalAdapters();
}
aioobe's answer is a good approach to take, but I'd also suggest something a little bit different:
If you are requiring a method to return an array of a certain size, you might want to question why an array is the appropriate return type for this method in the first place, rather than using a simple POJO which can easily encapsulate the idea of "3 BaseAdapters", i.e.:
public class ThreeAdapters {
BaseAdapter getAdapter1() { ...}
BaseAdapter getAdapter2() { ...}
BaseAdapter getAdapter3() { ...}
}
It's a lot clearer to everyone involved if you encapsulate the idea of "return 3 adapters" into it's own class so that this can be used as the return type (of course, you may find a more appropriate name for the class).
In Java, the size of an array is not part of its type. Or to put it another way, all array types with a given base type are the same. Furthermore, you cannot a method signature that places restrictions on the size of an array typed parameter or result.
This means that you are left with the coding the method to test (in your case) the length of the array it is about to return. This is probably not going to help you much, since I assume that you are trying leverage static typing to enforce the "tripleness" of your arrays. From this perspective #matt b's answer is on the money, though you could make do it in a way that still gives you arrays (of length 3):
public class AdapterTriple {
private Adapter[] adapters;
/**
* This constructor may throw an exception
*/
public AdapterTriple(Adapter[] adapters) {
if (adapters.length != 3) {
throw new IllegalArgumentException("array length is wrong");
}
this.adapters = adapters;
}
/**
* This constructor won't throw an exception (apart from Errors)
*/
public AdapterTriple(Adapter adapter1, Adapter adapter2, Adapter adapter3) {
this.adapters = adapters = new Adapters[] {
adapter1, adapter2, adapter3};
}
/**
* #return an array of 3 adapters.
*/
public Adapter[] {
return adapters;
}
}
In summary, you cannot enforce array size constraints statically in Java. You have to do it dynamically, but you can take steps to make runtime errors unlikely.

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