Java Reflection for creating new objects - java

Is there a way to create primitive data type variables use Java Reflection?
For example,
public Object createObj(String type, String value){
if(type.compareTo("char") == 0)
//return a char
else if(type.compareTo("int") == 0)
//return an int
....
}

The common idiom I see here is to use Class.forName().
public static Object makeNew(String type) throws Exception {
Class clazz = Class.forName(type);
return clazz.newInstance();
}
For int, char you have to use the names of their respective class-types, you can't actually make a primitive. "java.lang.Integer", "java.lang.Character", etc. respectively. You'll need to check those specially if you want to pass in "int", "char", etc.
Adding a "value" as a string is much harder. Most classes will not have a way of changing a string into an initial state. You'll definitely have to special case the primitives to provide an initial value. Overall, I think this is not a great way to approach whatever problem you are tying to solve.
So you mention in your comment about using setter methods. One problem is how do you determine which setter do you call? If you pass a parameter of "10", for a JButton, is that the setAlignmentX, setAlignmentY, or the setText method?
At this point you have to go whole hog on it.
<class>
<name>javax.swing.JButton</name>
<set><method>setAlignmentX</method><value>10</value></set>
</class>
Now you have the problem that some setters take other classes as parameters. And some classes are immutable (Integer and Character are), they have no setters at all, you'll have to call a ctor.
You're basically getting into serialization here (which is a very hard problem). Take a look at XmlEncoder and XmlDecoder, they do something close to what you want. https://docs.oracle.com/javase/8/docs/api/java/beans/XMLEncoder.html

Related

Enum or List or Set : Which is better to use [duplicate]

I am aware there are similar questions, and I have read the answers, but maybe I'm just not quite grasping the full difference of its use, even though I understand their difference when for example, initializing a String. Example:
String[] favorite = {"dog", "cat", "alien"};
vs
enum favorite = {dog, cat, alien}
Or maybe the use of either in the above case is similar, but their difference can be grasped better in another example? Is it that enum can clearly store more properties for a variable when creating the class?
The big advantage of enum is that the compiler checks for typos (type safety). For instance, if you assign the value "dag" to a string, the compiler does not complain. But, you cannot assign the value favorite.dag to a variable (of type favorit). Also, enum makes the code more readable and it is faster (comparison, for instance).
Just like #AhmadWabbi said, it's mostly type safety.
With enums you also have the ability to write methods corresponding to the enum.
For instance:
public enum Favorite = {
dog("woof"),
cat("meow"),
alien("zoink")
private String sound;
Favorite(String sound) {
this.sound = sound;
}
public String makeSound() {
return sound;
}
}
Which then let you call the method on a known enum (Favorite.dog.makeSound()) or if the enum is a parameter to another method.
The biggest advantage is that an enum is type-safe. An enum value can only take on one of the defined values (or null). (Note that an enum in Java is not like an enum in C++ or C#, where it is more like an alias for an int).
If you use a type like String or int, you can assign to that any value that fits in a String or int, even if it's not one of the limited set of values that you want it to contain.
It also makes programs easier to read, because when for example a method takes an enum type as a parameter, you immediately know what it means, and what values are valid - if it would, for example, take a String, you don't automatically know which strings are valid inputs and which are not.
There is no need to be too sophisticated with a program.
If you have three strings use the string array. If you have three distinct entities which differ by something else in addition to their names, use enum (on which you, evidently, will then be operating somehow).
Enums are easy to add new functionality to your code. Strings have their limits, you can decide yourself if you need all the benefits of enums or string will do for the job.
For example:
public enum favourite {
dog, cat, cow;
public boolean barking(){
switch(this){
case dog:
return true;
case cat:
case cow:
return false;
}
throw new AssertionError();
}
}
Enum sort of create a namespace . Thus two constants with same name can belong to different enums. Of course , you can emulate it with ArrayList but its not intuitive , because its supposed to acts as a container rather than a logical namespace holding constants.
You can compare it old style enums from C++ , where two enum declarations holding a same named constant shows a error . With new style class enums in c++ adds sort of namespace to it , which was not possible earlier.
And yes
Enums in Java already have a name-spacing feature.
By the way , Enum and ArrayList both have different purpose.
The biggest advantage of enums is that they are type-safe: a variable of an enum type can only hold values defined in that enum. By the way, in some circumstances this can be a big disadvantage, a show-stopper even: if the possible values are not known at compile time (for example, because you need to fetch them from a database at run-time) you cannot use enums.
Although I do not see a clear advantage of it (and if I don't see a clear advantage I would always use the established coding practice, which is using an enum), you can certainly use strings as a kind of enums. Performance will probably be a bit worse because of the string comparisons, but in most cases unnoticeably so.
However, I would strictly advice against your array example, for the following reasons:
Arrays are mutable. If your project is large enough, someone will eventually write favorites[0] = "beer"; and thus cause mysterious bugs in unrelated parts of the code.
Using an array has no advantage in readability. The meaning String myFavorite = favorites[1]; is completely opaque, whereas String myFavorite = "cat"; or Favorite myFavorite = Favorite.CAT; are immediately clear.
String literals can be used in switch statements, but not expressions like favorites[2]. So switch (myFavorite) { case favorites[2]: ... } is not legal Java (whereas switch (myFavorite) { case "alien": ... } is).
If you really want to use Strings as enums, then define String constants:
public static final String FAV_DOG = "dog";
public static final String FAV_CAT = "cat";
public static final String FAV_ALIEN = "alien";

Best strategies when calling a method that should modify more than one variable

I am pretty new to Java, I have to convert C/C++ code to Java and I am running into obstacles. Because of the way variables are passed to the methods, their modification in the method is not straightforward, and I have no idea what is the most reasonable approach to take. Sorry for the pseudocode examples, I hope they will clearly explain what I am talking about without delving into unnecessary details.
I need something that would be equivalent to C
ModifyMyString(type1 &t1,type2 &t2);
(return type doesn't matter, it can be void) as I need the function to modify both t1 and t2.
I can easily modify one of the variables, say t1, by declaring in Java
type1 modifyMyString(type1 t1, type2 t2);
and assigning the returned value to
t1 = modifyMyString(t1,t2);
but it is only half of a success, as the new value of t2 is lost.
I can declare new class
class JustToPassTwoVariables {
type1 t1;
type2 t2;
JustToPassTwoVariables(type1 tt1, type2 tt2) { t1 = tt1; t2 = tt2; }
}
and do something like
JustToPassTwoVariables jtptv = modifyMyString(JustToPassTwoVariables(t1,t2));
but I feel like it is clumsy and makes the code unreadable.
In desperation I could also resign the idea of using a modifyMyString method, and repeat all the code locally in each place I would call modifyMyString - but it makes even less sense than using JustToPassTwoVariables class.
Is there a correct (or at least widely used, accepted as a standard, whatever) strategy to code such things in Java?
The recommended way in java is (in some people's opinion the clumsy way) to create a class containing the two fields and return an instance of that class.
I feel that it is much less clumsy if you stop and think about what the method is actually doing, and taking care to properly name both the method and the class returning the two values.
The simple answer is no. This sort of feature is not allowed in Java.
The correct way to do it is to pass in the object to be modified not the two variables. After all in virtually all cases those variables are already wrapped in an object, in cases where they aren't they often easily can be.
Either split the function into two functions and call it once for each variable, or wrap the variables into an object and pass that object into the function.
Don't forget Java allows Inner Classes which makes this sort of thing less painful.
You can't return two values from a method in java. The way is to return an object and set all the values in it. i.e. In your case, you need to create a value container class i.e. say Result class that will have two fields storing the type1 and type2 value in it. The return type of the method would be of value container object type i.e. say Result instance with two fields in it - type1 and type2
Example :
Result result = modifyMyString(t1,t2);
result.getT1(); //gets t1 value
result.getT2(); // gets t2 value
Please learn about setters and getters in Java to work on the class or object level fields
In Java if you want to do this you would generally make type1 and type2 into object whose values can be modified. The method can then modify the values of the parameters to get the desired effect. For example :
void myMethod(type1 arg0, type2 arg1) {
arg0.setValue(newValue0);
arg1.setValue(newValue1);
}
If type1 and/or type2 do not have any way of changing their values (e.g. they are of type String) then you would either make a wrapper class for each of them e.g.
class Type1Wrapper {
private type1 type1;
type1 getType1() {
return type1;
}
void setType1(type1 newType1) {
type1 = newType1;
}
}
or you would make a wrapper for both of the types simultaneously like you have in your question (although the method return type will be void and the method will modify your wrapper's values)
There are several methods to modify a group of objects "of the same type/class". The simplest of them being, add them to a "list" pass that list to your modification function, do whatever modifications/additions/deletions etc.. The list reference will be automatically available outside with the "changes made in the called function" .
So, you can do
List<String> l = new ArrayList<String>();
l.add("Hello");
l.add("world");
ModifyMyString(l);
// here also l = "hello" , "world" , "added"
public void ModifyMyString(List l)
{
l.add("added"); // now l = "hello" , "world" , "added"
}
Java is an OO language so to get the best out of it you should look to an OO solution. It's hard to give you a definite solution with this abstract example but this is how I would approach this.
You mention that t1 and t2 both need to be updated by this modify procedure/method. Also that they need to be updated at the same time, if they were unrelated then you could just call modify on each string in turn. If these two strings are related like this then it's likely they belong to the same type.
So we need a class containing type 1 and type 2.
public class TypeContainer
{
private String type1;
private String type2;
.. getters and setters
}
Obviously you'll want a better class name.
You suggest something similar yourself but call it JustToPassTwoVariables. This is missing the point of OO. You could write a simple wrapper like this and pass it to some other method to modify the values but a more OO approach would be to add the modify method to this class itself.
...
public void modfiy(String val1, String val2)
{
type1 = val1;
type2 = val2;
}
...
I'm not sure what your modify is trying to do but in this case I would probably have these as two separate setter methods. This is quite an abstract example!
Basically I would avoid having the modify method in some other unrelated class. You should look to group common related attributes into classes and then write methods in those classes for any actions you need to take (such as modify).
Trying to convert a procedural C program into an OO Java program sounds like a PITA. It's a complete paradigm shift. Having said that I have seen automated conversions which while technically Java are still very procedural. Not very pretty and hard to maintain but was done for political reasons.
Java discourages this strategy beacause in-variable should be immutable, but if you have to migrate from C/C++/C# and you have a lot of "void function with parameters passed as in/out", you can create a Custom "Reference" class like this and you can incapsulate the original object.
public class CustomRef {
public Object internal;
public CustomRef(Object object) {
this.internal=object;
}
}
then when you call
CustomRef ref1= new CustomRef(myParams1);
CustomRef ref2= new CustomRef(myParams2);
myFunction(ref1, ref2);
myParams1 = ref1.internal;
myParams2 = ref2.internal;
the function is
void myFunction(CustomRef ref1, CustomRef ref2) {
Object param1 = ref1.internal
// a lot of code
ref1.internal = param1;
}
really discouraged way ... such as using ArrayList, arrays [] to "pass by reference".
NOTE: this way is a waste of resource; CustomRef instance should be reused through object pool (another discouraged way).
I would use a StringBuffer. You can initialize it with a String and convert it back to a String

Dynamically casting to primitives in Java

Edit: This has since been solved. Thanks to everyone who helped. Invoking the method after casting the object as the correct wrapper class worked. But String.valueOf() is much, much simpler to achieve the same effect.
Hello--
What I'm trying to do may not even be possible. I've spent a few hours now researching and experimenting with various things, so I figured I'd finally ask around to see if anyone knows if this is even possible.
Is it possible, using reflection, to dynamically cast a wrapper for a primitive of an unknown type as a primitive?
I'm basically trying to create a generic toString function which can handle the conversion of any type of primitive to a string. Such a seemingly simple thing is frustratingly difficult (and I am aware I could just test each type to see if it is of type Wrapper.class and cast it specifically, but at this point I'm just pursuing this out of stubbornness).
The following throws a ClassCastException. The primClass class appears to be the right one (gives "int" when printing primClass.getName()).
private String toString(Number obj){
String result = "";
try{
Class objClass = obj.getClass();
Field field = objClass.getDeclaredField("TYPE");
Class primClass = (Class)field.get(obj);
Method method = objClass.getMethod("toString", new Class[]{primClass});
Object args = new Object[]{primClass.cast(obj)};
result = (String)method.invoke(null, args);
}catch(Exception ex){
//Unknown exception. Send to handler.
handleException(ex);
}
return result;
}
So I'm a bit at a loss, really. Anyone have any ideas? Any help would be greatly appreciated.
Perhaps I'm missing something, but obj.toString() would do.
If you look at the implementations, it is calling String.valueOf(value) which in turn calls Double.toString(..) or Long.toString(..) or whatever. So, calling toString() automatically calls the required method. Without any reflection from your part.
You might want to have a look at Apache Commons Lang, Especially ToStringBuilder.reflectionToString(). Even if you don't want to introduce a dependency just for a toString(), it's open source so you can have a look at the implementation.
method.invoke accept the Wrapper types instead of the primivtes types.
Perhaps there is something I don't understand in your question but for primitive, you can do ""+primitive to cast it to a String.
What you are trying to do doesn't really make sense.... when your function is called with a primitive argument (e.g. an int) then it will automatically get boxed into an Integer. So you might as well just call obj.toString() on it.....
However if you really want to do something special with primitives, you might want to do something like the following using method overloading:
private String toString(Object obj){
return obj.toString();
}
private String toString(int intValue) {
// code to return string for the primitive int case, assuming it is different
}
// more overloads for other primitive argument types as needed.....
This can be a very useful technique for dealing with primitives in some cases.
The immediate problem in your code is that obj is an Object, and therefore cannot be an instance of a primitive type. (It must be an instance of the corresponding wrapper type). The primClass.cast(obj) call must fail for any primitive type class.
But if you simply want to turn a primitive wrapper instance to a String, just call the instance's toString() method.
String.valueOf(arg) will do it nicely too.

How to create IN OUT or OUT parameters in Java

In PL/SQL (or many other languages), I can have IN OUT or OUT parameters, which are returned from a procedure. How can I achieve a similar thing in Java?
I know this trick:
public void method(String in, String[] inOut, String[] inOut2) {
inOut[0] = in;
}
Where the in parameter represents an IN parameter and the inOut parameter can hold a return value. The convention would be that String[] inOut is an array of inOut.length == 1.
That's kind of clumsy.
EDIT Feedback to answers: Other tricks include:
holder/wrapper classes, but I don't want to introduce any new types, callbacks, etc.
return values: I'd like a general solution. I.e. one with several IN OUT parameters involved.
wrapper for IN OUT parameter as a return value: That's a viable option, but still not so nice, because that wrapper would have to be generated somehow
Does anyone know a better way to achieve this generally? The reason I need a general solution is because I want to generate convenience source code from PL/SQL in a database schema.
My question would be: Why doesn't method return something? Rather than setting an in/out argument?
But assuming you absolutely, positively must have an in/out argument, which is a whole different question, then the array trick is fine. Alternately, it's not less clumsy, but the other way is to pass in an object reference:
public class Foo {
private String value;
public Foo(String v) {
this.value = v;
}
public String getValue() {
return this.value;
}
public void setValue(String v) {
this.value = v;
}
}
// ....
public void method(String in, Foo inOut) {
inOut.setValue(in);
}
(Or, of course, just make value public.) See? I said it wasn't less clumsy.
But I'd ask again: Can't method return something? And if it needs to return multiple things, can't it return an object instance with properties for those things?
Off-topic: This is one of the areas where I really like the C# approach. One of the arguments against in/out arguments is that they're unclear at the point where you're calling the function. So C# makes you make it clear, by specifying the keyword both at the declaration of the function and when calling it. In the absense of that kind of syntactic help, I'd avoid "simulating" in/out arguments.
Java copies anything you pass as an argument. If you pass a primitive, inside method you have copy of that primitive, and no modifications will affect the actual variable outside method. If you pass object, you pass copy of reference, which actually references to the original object. This is the way how you can propagate modifications to the context of something that called the method - by modifying the state of the object that the reference is 'pointing' to. See more on this: Does Java Pass by Value or by Reference?
There's no direct way. Other technique include:
Passing a holder object (a bit like your 1-ary array)
Using, e.g., an AtomicInteger
Passing a more useful object from a business perspective that happens to be mutable
A callback to a custom interface for receiving the result
If you think about it, the array trick is not dissimilar to passing a T* in C/C++

Efficient way to convert unknown objects to appropriate Method.invoke arguments?

I'm writing a reflection-based RPC service that gets arguments passed in via a variety of mechanisms. Sometimes the arguments correctly match the parameter type, sometimes they're always strings, and sometimes they're wrapped up in dynamically typed "scripty" objects that need the appropriate value extracted out.
Before I can call method.invoke, I need to build the argument list, something like this:
Object a[] = new Object[method.parameterClasses.length];
for (int i = 0; i < a.length; ++i)
{
a[i] = prepare(method.parameterClasses[i], rpc.arguments[i]);
}
The "prepare" method looks something like:
Object prepare(Class clazz, Object o)
{
if (o == null) return null;
if (clazz == o.getClass()) return o;
if (clazz == String.class) return o.toString();
// skip a bunch of stuff for converting strings to dates and whatnot
// skip a bunch of stuff for converting dynamic types
// final attempts:
try
{
return clazz.cast(o);
}
catch (Exception e)
{
return o; // I give up. Try the invoke and hope for the best!
}
}
During unit testing, I was recently rather surprised to discover that a method passed a boxed Integer that expected a primitive long was actually failing the cast and falling through the bottom, and then being properly converted by something during the invoke(). I'd assumed the call to "cast" would do the trick. Is there any way to explicitly perform and check the argument conversion done normally by invoke?
Lacking that, I thought about putting in explicit checks for numeric types, but the number of permutations seemed out of hand. When I add support for extracting numbers from the script dynamic types and converting strings, it gets even worse. I envision a bunch of conditional typechecks for each possible numeric target class, with Integer.decode, Long.decode etc for the String arguments, Short.decode, and Number.intValue, Number.longValue, etc. for Numbers.
Is there any better way to do this whole thing? It seemed like a good approach at first, but it's getting pretty yucky.
It is indeed surprising, but that is the current behavior. See bug 6456930.
In terms of a better way to approach the problem, at its core, no you will have to define all of those rules. There are better (more maintainable) patterns that a series of if's, though. For starters, I'd have some strategy objects that can be invoked for one side of those objects (probably the class side) so that you look up the appropriate object (say from a Map) based on the class, and then you can limit your conversions to one side (each object would be concerned about how to get things into that particular class). That way when there is a new kind of class conversion that you need to support, you can write an object for it, test it separately and just plug it into the map without changing further code.
There's really not a better way. There are an infinite number of potential conversions, but only a tiny number that really make sense. Rather than trying to give clients complete freedom, I recommend specifying a contract for type coercion.
As a starting point, check out the type conversion rules used by the JSP Expression Language. They are quite powerful, and allow many types of conversions to take place, but they are also well-defined, easy to remember—and possible to implement.
There are at least a few shortcuts you can take to simplify your code:
If the parameter is an instance of java.lang.Number and the argument type is either byte, short, int, long, float or double (either as primitive, or as wrapper class), you can use the methods in Number like byteValue(), shortValue(), etc to convert the parameter.
If the parameter is an instance of java.lang.String and the argument type is one of the above mentioned, you can use the static valueOf(String) method in the respective class for conversion.
Converting further, and perhaps even proprietary types would of course need more work. If it's really necessary and your prepare method is getting to large, you should perhaps consider abstracting the conversion behind an interface and allowing pluggable conversion providers to be dynamically added to the application?

Categories

Resources