Java : Class wrapper using generic - java

I would in some way store many different type in a HashMap, but in a way that when i extract them they will be well typed (and not an object).
So i think about a wrapper that use generics
public class Value <T>
{
private T innerValue ;
public Value ( T _value )
{
innerValue = _value ;
}
public T read ()
{
return innerValue ;
}
}
but it does not work, for a test i made :
Value <Integer> va = new Value <Integer> ( 1 ) ;
Value vc = va ;
int restA = vc.read();
but i get a design time error, because vc.read() will return an Object() and not an Integer.
So what should i do to avoid this behaviour? (if possible i would a solution that prevent 'va' from losing information about T instead of other workaround)
Thanks in advance for any help.

You casted va to a raw Value, vc. When you use the raw form of a class, your T generic type parameter is replaced by Object. So you cannot assign an Object to an int.
If you just call va.read(), then it will return an Integer, which will be unboxed to an int upon assignment to restA.

I would in some way store many different type in a HashMap, but in a
way that when i extract them they will be well typed (and not an
object).
Short answer is: this is not possible. And type erasure is not the reason: it simply does not make much sense to have this information at compile time. Suppose that Java compiler had some kind of mechanism to keep track of the types of objects stuffed into a HashMap. Then it also would have to cope with something like this:
HashMap<Integer, Value<?>> myMap = new HashMap<Integer, Value<?>>;
if (Math.random() > 0.5) {
myMap.put(0, new Value<String>("hello world"));
} else {
myMap.put(0, new Value<MacaroniExtruder>(new MacaroniExtruder()));
}
[whatDoYouWantToWriteHere?] value = myMap.get(0);
What you want is probably rather something like "type-union". Unfortunately, it does not exist neither in Java, nor in Scala (where we have case-classes, which are almost just as good for that). So all you can do is basically:
A) Use polymorphism, define a proper interface, so that the concrete implementations become completely irrelevant, and work with that interface as second argument to your hash Map (preferred).
B) Use instanceof and long if-else switches (ugly)

Related

What is Java equivalent of C# default(T)

I'm currently working on generic Sum projection for one of my projects. The code is like,
public class Sum<T,U extends Number> implements IProject<T,U,U>
{
#Override
public U eval(Iterable<T> tList, Function<T,U> property)
{
U total;
for (T t : tList)
{
total += property.apply(t);
}
return total;
}
}
However there is a little glitch here since I need to initialize the total (obviously to 0). But is there anyway to do it in java like in C# I could use default(U).
Java's equivalent to C#'s default(T) is null, which clearly would not work in your case, because you would get a NullPointerException the first time you tried to add something to your total.
In order to initialize your total you would need a factory method in java, but it still would not work, because:
you cannot use += on generics in java.
java.lang.Number is immutable, so you cannot add anything to it.
You have two options.
The massively overengineered approach:
Define a new interface called, say, MyNumber which contains an add method, and write associated non-immutable numeric classes implementing this interface, so your code would then look like this:
#Override
public <T extends MyNumber> T add( T total, Iterable<T> myNumbers )
{
for( T myNumber : myNumbers )
total.add( myNumber );
return total;
}
(You would also need to write a factory so that you can create an instance to hold your total without knowing precisely what type it is.)
The pragmatic approach:
Write cascaded if statements like this:
if( number instanceof Integer )
{
//declare int total
//loop to sum integers
//box the total into a Number
}
else if( number instanceof Long )
{
//declare long total
//loop to sum longs
//box the total into a Number
}
...
Generics only exist for reference types anyway, so this would always be null. There also seems to be an implicit assumption that the + operator is defined for U - are you sure there aren't more constraints on what U can be? Also have you looked at doing Stream.map followed by Stream.reduce? (I assume you are using Java 8 as you have Function)
EDIT I think what you are looking for is the monoid pattern. It doesn't exist in Java but you can define it yourself -
interface Monoid<T>
{
T getZero();
T add(T left, T right);
}
And thus your example would become
public U eval(Iterable<T> tList, Function<T,U> property, Monoid<U> m)
{
U initial = m.getZero();
return StreamSupport.stream(tList.spliterator(), false)
.map(property)
.reduce(initial, (uLeft, uRight) -> m.add(uLeft, uRight));
}
but that would require changing the signature of eval, which might not be possible as I see it's annotated #Override.
This approach is extensible to Lists and Strings with Concatenation, Sets with union and Maps where the value is itself a monoid, "adding" all values of a given key, and functions under composition where the "zero" is the identity function.

Using an ArrayList<Class?> for casting?

Previous question
I have the following code:
ArrayList<Object> list = new ArrayList<Object>();
list.add("StringType");
list.add(5);
list.add(new RandomClass());
List<Class<?>> classes = new ArrayList<>();
classes.add(String.class);
classes.add(int.class);
classes.add(RandomClass.class);
for (int i = 0; i < list.size(); i++) {
if (classes.get(i).isInstance(list.get(i))) {
...
}
}
if (isvalid)
mymethod(...);
public void mymethod(String string, int num, RandomClass randomClass){ }
Now I'm trying to cast the object into the right type with a method using a string argument.
Instead of:
mymethod( (String) list.get(0), (int) list.get(1), (RandomClass) list.get(2) );
I would like to reuse the definition created above for the cast.
mymethod( ( define.get(0) ) list.get(0), .... );
I've also tried using the Class.cast(obj) but of course it returns a type '?' which again defeats the purpose of casting it again using (String).
What is type safety?
In computer science, type safety is the extent to which a programming
language discourages or prevents type errors.
If code is type safe, then the compiler can verify, at compile time, that all the types are correct:
String getName() {
return "name";
}
The compiler knows that "name" must be a String so it can verify that this code will never throw a type error.
Once you do something like:
int getNumber() {
(int) number;
}
The need to explicitly cast to int tells you that this code has an error condition, namely when number is not of type int or a type that is assignable to int.
How does it affect you?
Your code:
define.get(0).cast(list.get(0))
You want the return type of this statement to be of the type of get(0). But the compiler has no way of knowing, at compile time, what define.get(0) returns. This is inidcated to you by the return type.
You have a List<Class<?>>, i.e. a List of a class of "I don't care what type". You then use a member of this List to cast a member of your other List - the only result can be an "I don't care what type".
You can hack around this with:
<T> T get(final int i) {
return (T) define.get(i).cast(list.get(i));
}
This will happily compile:
final String thing = get(0);
As will:
final int thing = get(0);
i.e. all that you have done is to endogenise the cast. The error condition still exists.
define.get(0).cast(list.get(0)) would attempt to cast list.get(0) to the required type.
In order to be able to select the appropriate method, the compiler needs to know at compile time what the types of the arguments are. Or at least a general category such as List<?> etc.
This is needed to support overloading of methods. There can be many methods with the same name, but with different parameter types.
Since you are asking the VM to call a method when it can't determine which exact method you want to call, because it doesn't know at compile time what the types of your parameters are, what you ask cannot be done in Java.
Here is the relevant section from the Java Language Specification.
What it says is that the system selects at compile time which method signature to use, and then, at run time, the particular implementation of that method signature that's correct for the given instance.
You don't actually need to store object's class separately
list.get(0).getClass()
will get you the class of the stored object and then you can use what #Eran suggested
and
list.get(0).getClass().getName()
will get you the String name of your class

Define generic/variable type for data structure

I am having a data structure (LinkedHashMap) but the problem is that the (second) value should be of variable type since I can put there type String or type int or any primitive type so my question is:
Is there a way to define a variable type for it that can get any value type?
This is what I'm having:
private LinkedHashMap<String, String> keyVal;
I want something like this:
private LinkedHashMap<String, anyValue> keyVal;
private LinkedHashMap<String, Object> keyVal;
You can use Object for that. But do remember that while trying to get data back from this map(sometime later), you may face difficulty in casting the Object to your required data type, as you may not know, what data type is actually present.
Hence, its advisable to avoid such implementations.
You cannot have a generic type be a primitive type. If you want to be able to store anything in your map, you can have the "value" generic type for the map be Object:
private LinkedHashMap<String, Object> keyVal;
You can still store what looks like primitives types due to autoboxing, i.e.
keyVal.put("one", 1);
will place an Integer, even though you specified an int.
No, the closest you can have is Object as a second argument.
Now, I would advise to rethink what you need to accomplish, since this is actually going against what generics were created for.
If you have a bound type and want to maintain some flexibility, then you could use something like <String, ? extends SomeType>.
Mixing several types of Objects in the same data-structure is not advisable in Java (if this is good or bad, is beside the point), but type safety goes a long way in preventing weird errors along the line.
Try to think about how you would deal with this when you actually need to retrieve the objects... will you assume they're Strings? What are you going to do with them?
You say you want to have a Map< String, Primitive type>.
A specified by the JLS, primitives are NumericType or boolean, NumericType are IntegralType or FloatingPointType.
If your need is not primitive but only NumericType, you may use java.lang.Number:
Map< String, Number >
Another way is to define a class Any which hold all the possible attributes:
enum Type {
NULL,
INTEGER,
SHORT,
FLOAT,
...
}
class Any {
private int iValue;
private short sValue;
private float fValue;
...
private Type active = Type.NULL;
public void setInt( int value ) {
iValue = value;
active = Type.INTEGER;
}
public void setFloat( float value ) {
fValue = value;
active = Type.FLOAT;
}
...
public int getInt() {
if( type != Type.INTEGER ) {
throw new ClassCastException( type.name() + " is not an integer" );
}
return iValue;
}
...
}
It's up to you to put some check and throw exception if getInt() is called on a float holder. Everything is possible, transtyping like C language for example.
EDIT
You want String too, and String isn't a primitive.
You have to add the following below private short sValue; into the Any class:
private String sValue;
and the followinf below SHORT, into the Type enum:
STRING,
But, like others says, the best way is to avoid these weak type (fourre-tout in french).
You can use
private LinkedHashMap<String, Object> keyVal;
to leave the second type argument as general as possible.
It allows you to store any object as a value, because every class extends Object.
This leads you to the problem that you don't know what type of things are inside your map - you only know that they are of type Object what means you don't know anything.
So to use these objects again you would have to cast them back to their original type what may cause a runtime exception: ClassCastException.
Generics are about defining data structures for different types with the same code, but if you want to use a generic class you have to parameterize it with its type arguments. This ensures that the type is known at runtime and is the great advantage of generics (avoid ClassCastException).
However, you can still specify a more general type that allows multiple types.
For example, if you define it the following way you can store any object that implements Serializable.
private LinkedHashMap<String, ? extends Serializable> keyVal;
As you can see, this allows you to restrict the permitted types to a common property (i.e., to be a subclass of a more general type). That way, you use the map's values as objects of the more general class, because it's everything you know (and want to know) about the objetcs.
It's better to have a look at:
Generics lesson on Oracle.com.
Care when should use wild cards (?) and you should use Generics.
Using Object in type of LinkedHashMap<String, Object> keyVal; is not recommended.
Like some people said, you could use Object for generic variable type, especially while using generic method or not knowing what data type user would come, like this simple one:
import java.util.Scanner;
public class GenericMethod {
public static void main(String[] args) {
System.out.println("Type something that's yours: ");
Scanner sc = new Scanner(System.in);
Object thing;
thing = sc.next();
isMine(thing);
}
// Generic Method
public static <T> void isMine(T x) {
System.out.println(x + " is mine.");
}
}

Unsafe parameterized ArrayList cast after an instanceof check

Hi guys i got a problem with an unsafe cast operation.
Here is the problem. I gotta Constructor which accepts different types of Orders (PlayList, UserOperations, etc.) or should. So i decided to give it a Parameter as Object and check the type of the received once called. The Problem is one of those is a parameterized ArrayList (ArrayList < PlayList >) and since it is impossible to check a parameterized ArrayList I have to "dig" in. At first step i check if it is an ArrayList, at second I go into it an check the type of its content.
The problem afterwards is I get an unsafe cast warning which i dunno yet how to handle.
Greetings
public Order(int aTyp, Object aOrderContent) {
this.orderTyp = aTyp;
if (aOrderContent instanceof ArrayList< ? >) {
ArrayList<?> objList = (ArrayList< ? >)aOrderContent;
if (objList.get(0) != null && (objList.get(0)) instanceof PlayList) {
playList.addAll((ArrayList<PlayList>)aOrderContent) ;
}
} else if (aOrderContent instanceof UserOP) {
}
}
Rethink your design. Don't make the constructor take an Object. This is too opaque and allows consumers of your code to pass any type. It sounds like you should be using a generic class instead (though it's hard to tell based on your partial example). Possible solution:
// Might need an upper bound on T if you want to limit the allowed parameterizations
class Order<T> {
private final int orderTyp;
private final List<T> someList = new ArrayList<>();
public Order(int aTyp, List<t> aOrderContent) {
this.orderTyp = aTyp;
someList.addAll(aOrderContent);
}
}
Keep in mind it may be better to use an enum instead of int for the orderTyp, if you know (at compile time) all the possible type values.
Side note: if a List is empty, List#get(0) with throw an exception, not return null.
Instead of making the constructor take an Object overload you constructor. Have one take an List<?> and one take a UserOP ect. Also, it would be ideal if all the options for the List extended from the same interface so you could have List<MyInterface> instead of List<?>

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