I have a game that runs on a similar system to games like terraria or minecraft, at least in the aspect of being blocky.
I have constructed it in a way where each block is an Object, and there is a specific class (extends a BlockObject archetype) for each type of block.
I have the game save the blocks in a file like following
I get the name of the instance of the Object i am saving, and store it in a string
I start writing the information of the given Object in a string that has the Name of the Class(signifieing what type of block it is Ex. a block that is an object of BlockGrass.java would be stored as BlockGrass).
Normally when reading information from a save file I am reading the save file, when it gets to the info of the blocks it first saves the Block type in a local string (BlockGrass in this case), also saves the positions (x cordinate, and y cordinate). Then it would run through a series of if statements like the following
if(blockType.equals("BlockGrass"))
{
blocksArray.add(new BlockGrass(...));
}
else if(blockType.equals("BlockStone"))
{
blocksArray.add(new BlockStone(...));
}
etc
now I want to make my game vary dynamic, and want it so that if someone decides to make a new Block class (Modding the game) they do not have to modifiey the MapReader class. so instead of running through a series of if statements as shown above (where everytime a new block class is created, a new if statement must be placed for that block), i want it so that it make a new object of a class that has the same name as the BlockType. to give you a better idea look at the following
BlocksArray.add(new blockType(...));
the reason what is shown above does not work is because blockType is a string that holds the name of the class i want to use. not a Class Name
How could i do something like that?, without using if-statements.
What you are trying to do is to take advantage of polymorphic behaviours from your BlockObject hierarchy. Therefore using class.forName is the good approach. Once you have invoked newInstance()on the Class variable you will need to cast it to the base class (the archetype as you called it) of your hierarchy of BlockObject class. We have guarantee that since the real class is extending BlockObject, it is a BlockObject according to the definition of inheritance.
Here is an example
public class GameLoader {
private List<BlockObject> blocksArray = new ArrayList<BlockObject>();
public Object getNewBlock(String blockClassName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class blockClass = Class.forName(blockClassName);
return blockClass.newInstance();
}
public void addNewBlockType(String typeName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
BlockObject castedType = (BlockObject)getNewBlock(typeName);
blocksArray.add(castedType);
}
}
Any method of the base class invoked on such object will display polymorphic behaviours.
This is not compiled and checked but it is just to indicate what must be done.
// first get the class
Class<?> rawclass = Class.forName(String);
// then check an object will fit where you want it.
if (BlockObject.class.isAssignableFrom(rawclass)){
// create the object, cast it to the correct type and add it
BlockObject object = (BlockObject) rawclass.newInstance();
blockArray.add(object);
}
There will be some exceptions to catch out of the forName and newInstance methods.
I've been bashing my head on this problem for a while now.
I'm dealing with properties setting using the DBus-java bindings for DBus. When Set is called, the value to set is wrapped in a org.freedesktop.types.Variant object from which I have to extract it. Normally if the data is a primitive I can use generics in the Set parameters and the bindings does the type conversion before calling the Set method.
However I am trying to set using a org.freedesktop.types.DBusStructType which is a complex type and which needs to be manually unpacked. So far I've gotten to the point where I can extract the type from the variant but I can't cast the value wrapped in the Variant to a DBusStructType even though it is clearly identified as a DBusStructType
The following code throws a ClassCastException: Cannot cast [Ljava.lang.Object; to org.freedesktop.dbus.types.DBusStructType when called with a DBus.Struct from a python dbus test. I have checked the variant signature is packed right, but I can't find a way to cast the object returned by the Variant.getValue() to the type specified by Variant.getType() and access the structure fields.
public void Set(String interface_name, String property_name, Variant new_value) throws Exception {
Type t = new_value.getType();
Object s = new_value.getValue();
t.getClass().cast(s);
System.out.println("Object cast to "+s.getClass().getName());
}
Any pointers would be really appreciated, I have started digging more into reflection as I'm still new to it but there is probably something I am missing.
I have not used the Type Interface at all, but it looks like the only known implementing class is Class. I would suggest Casting it as a Class and then calling cast.
public void Set(String interface_name, String property_name, Variant new_value) throws Exception {
Type t = new_value.getType();
Object s = new_value.getValue();
((Class)t).cast(s);
System.out.println("Object cast to "+s.getClass().getName());
}
hope this helps.
The Object returned by getValue() needs to be cast to the right type corresponding to the Dbus types. By digging a bit more into the DBusStructType and DBusStruct, the Object returned by Variant.getValue() is an Object[] in the case of a DBusStruct. Here is the working code:
public void Set(String interface_name, String property_name, Variant new_value) throws Exception {
Object[] s = (Object[])new_value.getValue();
System.out.println("client ID: " + (Long)s[0] + ", string: " + (String) s[1]);
}
Output:
client ID: 0, string: Hello, this is data.
Note that I do a signature check on the Variant in the final implementation before casting the Object[] or it will fail with other DBus types.
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.
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.
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());