problem faced while setting value using reflection - java

i am using reflection to copy values of fields from object of Class A to object of Class B.
However method in A returns Number, where as setter in B requires Long. Is there any generic way i could set the value. As of now as expected i get illegalArgumentException: argument type mismatch
class a
{
Number value1;
Number value2;
public Number getValue1(){return value1;}
public Number getValue2(){return value2;}
}
class b
{
Double value1;
Long value2;
public void setValue1(Double value){this.value1 = value;}
public void setValue2(Long value){this.value2 = value;}
}
Not sure if my question is unclear.

You could do
b.setValue2(a.getValue2().longValue());
But if a.value2 isn't actually an integer (e.g. it's a Double with a fractional component) this will lose data.
Correspondingly
b.setValue1(a.getValue1().doubleValue());
Edit
Ok I think I've got a grasp on your situation. Here's a dirty way to go about what you want to do. Basically you need to have a transform method which will transform a Number into another Number based on a chosen class. That class you get from the Method itself. So it will be something like this:
public static void main(String[] args) throws Exception {
A a = new A();
a.setValue1(1.0);
a.setValue2(5);
B b = new B();
Method[] methods = b.getClass().getMethods();
for ( Method m : methods ) {
if ( m.getName().equals("setValue2") ) {
m.invoke(b, transform(a.getValue2(), m.getParameterTypes()[0]));
}
}
System.out.println(b.getValue2());
}
private static Number transform(Number n, Class<?> toClass) {
if ( toClass == Long.class ) {
return n.longValue();
} else if ( toClass == Double.class ) {
return n.doubleValue();
}
//instead of this you should handle the other cases exhaustively
return null;
}
The reason you would otherwise get an IllegalArgumentException in the above is because with a, value2 is not being set to a Long, it's being set to an Integer. They are disjoint types. If a.value2 was actually set to be a Long instead, you wouldn't have that error.

You need to do the conversion:
// get the Number 'number'
Long l = new Long(number.longValue());
// store the Long
You could do it even more efficiently using autoboxing.

You can't do this in a 'generic' way, because a Number could be a Float, Byte etc.

Related

Provide arguments with a method

Is there a way in Java to create a method that would return the list of parameters of another method such that I am able to call
anotherMethod(method())
where anotherMethod has arbitrary arguments like
public void anotherMethod(int a, int b, String c)
And what is if the types stay the same, like with
public int add(int a, int b, int c)
If there is no such way, how could I model the list of parameters such that it would work? Is it a List or an array or something else?
If the number of parameters is fixed at the call site, you could use varargs
int add(int... numbers)
otherwise you'd use an array or collection
int add(int[] numbers)
You can then of course have another method provide the value of these parameters:
add(someOtherMethod())
Varargs
Java has a built-in feature to denote a variable length of arguments. It is called varargs (documentation) (variable arguments) and it only works if the type stays the same. The syntax for a method is like this:
public int add(int... values)
Note the int... values which denotes varargs. A caller can now call the method like
add(null) // Passing null
add(values) // Passing an int[]
add() // No arguments
add(a) // One int
add(a, b) // Two ints
add(a, b, c) // Three ints
add(a, b, c, d) // Four ints
...
Note the three special cases null, int[] and empty.
What Java does is it will convert the arguments into an array. So inside the method values will be a regular int[]. You could thus implement the method like
public int add(int... values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return sum;
}
If you, as a caller, want to pass the return value of a function you just need to make sure that it returns an array like int[]. So the following would work:
public int[] valueProvider() {
int[] values = ...
return values;
}
and then call it like
int sum = add(valueProvider());
Collection, Iterable and Stream
Besides that, if you don't want to use varargs or arrays, you can use Collections (documentation). A collection may be a List or a Set and so on. For example you could declare
public int add(Collection<Integer> values)
and feed it like
Collection<Integer> values = new ArrayList<>();
values.add(1);
values.add(2);
int sum = add(values);
An Iterable<Integer>, in contrast to Collection<Integer> would even be more flexible.
Using a Stream (documentation) would also work like a charm and is probably one of the most flexible variants since the source of a stream could be anything and nearly anything of the standard library supports a stream representation.
Changing type
Now note that what you searched for in the beginning, a method that is able to feed arbitrary arguments, is not possible in Java.
The main problem is that the types may change, so you may have a method like
public void doSomething(int first, String second, File third)
and you won't be able to feed the method with varargs, Collections or any of the presented methods.
In that case you will need a wrapper class like
public class DoSomethingArguments {
private int mFirst;
private String mSecond;
private File mThird;
public DoSomethingArguments(int first; String second, File third) {
this.mFirst = first;
this.mSecond = second;
this.mThird = third;
}
// Some getters
}
(or a generic tuple class, a triple in this case)
But then you would need to change the method to
public void doSomething(DoSomethingArguments arguments)
what is probably not what you wanted since you probably intended to not change the signature of doSomething.
But unfortunately there is no way to feed a method like this in such a way.
There is nothing that works the way you wish for at compile time. As the other answers are pointing out, there are varargs. But that is just syntactical sugar. That is just the compiler implicitly creating an array of a certain type for you.
But beyond that, there is reflection. Reflection allows you to dynamically inspect classes and methods at *runtime.
In other words: you can do something like
Object whatever = ...
Class<?> someClass = whatever.getClass();
And now you can ask someClass about the methods it has. And which parameters they need.
But as said: all of that is runtime only. And it the reflection APIs are very easy to get wrong. And you only find out at runtime, when some exception is thrown.
There is not direct way to pass multiple values in the way you want. But you can use a indirect way to pass a group of values of different type. I can think of two ways but their can be more.
Firs - Use a map, just insert the values you want to pass in the collection and pass the collection to the second method.
Second - Create a bean (Java POJO) to pass as parameter to the consuming method.
A small sample code.
class Sample{
private int a;
private String b;
private int c;
Sample(int a,String b,int c){
this.a = a;
this.b = b;
this.c = c;
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public int getC() {
return c;
}
public void setC(int c) {
this.c = c;
}
}
public class PassingExample {
public void consumerofInputs (Map<Integer, Object> input)/*(int a, String b, int c)*/{
System.out.println("I use three different inputs : int, string and int");
for (Map.Entry<Integer, Object> entry : input.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
}
}
public Map producingInput() {
Map<Integer, Object> input = new HashMap<Integer, Object>();
input.put(1, 10);
input.put(2, "input");
input.put(3, 89);
return input;
}
public Sample createClassAsInput(){
Sample input = new Sample(10,"class-input",30);
return input;
}
public void useSampleAsInput(Sample input){
System.out.println("\nUsing Class as input \nInt::"+input.getA()+"\nString::"+input.getB()+"\nInt::"+input.getC());
}
public static void main(String[] args) {
PassingExample example = new PassingExample();
example.consumerofInputs(example.producingInput());
example.useSampleAsInput(example.createClassAsInput());
}
}

Is there a Integer class in c#?

We have Integer class in JAVA, but I couldn't find any equivalent class in C#? Does c# have any equivalent? If not, how do I get JAVA Integer class behavior in c#?
Why do I need this?
It is because I'm trying to migrate JAVA code to c# code. If there is an equivalent way, then code migration would be easier. To addon, I need to store references of the Integer and I don't think I can create reference of int or Int32.
C# has a unified type system, so int can be implicitly boxed into an object reference. The only reason Integer exists in Java is so that it can be converted to an object reference and stored in references to be used in other container classes.
Since C# can do that without another type, there's no corresponding class to Integer.
Code migration won´t work out of the box for any type of language without any manual changes. There are things such as a class Integer that simply does not exist within (C# why should it anyway, see recursives answer), so you´d have to do some work on your own. The nearest equivalent to what you´re after is Int32 or its alias int. However you may of course write your own wrapper-class:
public class Integer
{
public int Value { get; set; }
public Integer() { }
public Integer( int value ) { Value = value; }
// Custom cast from "int":
public static implicit operator Integer( Int32 x ) { return new Integer( x ); }
// Custom cast to "int":
public static implicit operator Int32( Integer x ) { return x.Value; }
public override string ToString()
{
return string.Format( "Integer({0})", Value );
}
}
The beauty of C# is that it has a unified type system. Everything derives from object, even primitive types. Because of this, all keywords are simply aliases for a corresponding class or struct. Java does not use a unified type system, so a separate Integer class is required to wrap the int primitive. In C# int is synonym for the Int32 struct.
What you're looking for has been right in front of you the whole time. Start using the dot notation directly on the int keyword (i.e. int.whatever()) to access the all goodness of the .NET version of the Javian Integer class.
I did some testing with Nullable types in a console application and it appears that they do not behave as you wish. For example:
static void Main(string[] args)
{
int? x = 1;
Foo(ref x);
Console.WriteLine(x);//Writes 2
}
private static void Foo(ref int? y)
{
y += 1;
var l = new List<int?>();
l.Add(y);
l[0] += 1;//This does not affect the value of x devlared in Main
Console.WriteLine(l[0]);//Writes 3
Console.WriteLine(y);//writes 2
Foo2(l);
}
private static void Foo2(List<int?> l)
{
l[0] += 1;
Console.WriteLine(l[0]);//writes 4
}
But if you roll your own generic class to wrap primitive/value types for use within your application you can get the behavior you are expecting:
public class MyType<T>
{
public T Value { get; set; }
public MyType() : this(default(T))
{}
public MyType(T val)
{
Value = val;
}
public override string ToString()
{
return this.Value.ToString();
}
}
static void Main(string[] args)
{
var x = new MyType<int>(1);
Foo(x);
Console.WriteLine(x);//Writes 4
}
private static void Foo(MyType<int> y)
{
y.Value += 1;
var l = new List<MyType<int>>();
l.Add(y);
l[0].Value += 1;//This does affect the value of x devlared in Main
Console.WriteLine(l[0]);//Writes 3
Console.WriteLine(y);//writes 3
Foo2(l);
}
private static void Foo2(List<MyType<int>> l)
{
l[0].Value += 1;
Console.WriteLine(l[0]);//writes 4
}
int, int? and System.Int32 are all struct and thus value types and does not compare to Java's Integer wrapper class which is a reference type.
System.Object class though a reference type can cause issue as boxing creates immutable object. In short, you can't alter a boxed value.
int a = 20;
Object objA = a; //Boxes a value type into a reference type, objA now points to boxed [20]
Object objB = objA; //Both objA & objB points to boxed [20]
objA = 40; //While objB points to boxed [20], objA points to a new boxed [40]
//Thus, it creates another ref type boxing a 40 value integer value type,
//Boxed values are immutable like string and above code does not alter value of previous boxed value [20]
Console.WriteLine($"objA = {objA}, objB={objB}");
//Output: objA = 40, objB=20
What exactly corresponds to Java's Integer is a custom generic wrapper class.
int a = 20;
Wrapper<int> wrapA = new Wrapper<int>(a);
Wrapper<int> wrapB = wrapA; //both wrapA and wrapB are pointing to [20]
wrapA.Value = 40; //Changing actual value which both wrapA and wrapB are pointing to
Console.WriteLine($"wrapA = {wrapA}, wrapB={wrapB}");
//Output: wrapA = 40, wrapB=40
Console.ReadKey();
Implementation of the wrapper class is given below:
public class Wrapper<T> where T : struct
{
public static implicit operator T(Wrapper<T> w)
{
return w.Value;
}
public Wrapper(T t)
{
_t = t;
}
public T Value
{
get
{
return _t;
}
set
{
_t = value;
}
}
public override string ToString()
{
return _t.ToString();
}
private T _t;
}
As pointed out in other answers, C# has a unified type system so everything derives from object. If you need to handle null values then use int? to specify that the integer object can be null.
c# have a integer type called int link is here
https://msdn.microsoft.com/en-us/library/5kzh1b5w.aspx

How to implement a basic pointer

I know here is no pointer in Java. But how do I change a value in the calling scope? For instance, I want to write a function that takes an integer num, set the integer to 0 if it's greater than 21, otherwise do nothing.
In the main, my code is as follow:
int a=34;
KillOver21(a);
System.out.print(a);
I expect an 0.
Java is pass by value, so a copy of the parameter a is sent to the method, so modification to a in the method will not affect the original argument a in main
The max you can do is return int from KillOver21(a) method
int z = KillOver21(a); // This will return 0
System.out.print(z);
But you can achieve something like that with custom objects, say you have a class
class AHolder {
public int a;
}
then you can expect AHolder instance to change
public static void main(String [] args) {
AHolder a = new AHolder();
a.a = 34;
killOver21(a);
System.out.println(a.a);
}
public static void killOver21(AHolder b) {
if(b.a > 21) {
b.a = 0;
}
}
Since in the latter (even if its Pass by Value) , the reference is copied and both reference point to same object. So changes made inside the killOver21 method actually changes the object.
It is simply not possible, Java supports pass by value. int a's value will be copied to the function.
You could use Object instead of primitive where the reference value will be copied to your function by which you can get the actual object and modify it.
Fundamentally impossible in Java, period. int are immutable, and passed by value. You would need to create a mutable int type:
class MutableInt {
private int value;
public MutableInt(int value) { this.value = value; }
public getValue() { return this.value; }
public setValue(int value) { this.value = value; }
}
Then:
void KillOver21(MutableInt m) {
if(m.getValue() > 21) { m.setValue(0); }
}
However, be aware the mutable types that represent concepts that are defined by their value rather than their identity are generally an extremely bad idea. But, this is the only way to achieve what you're trying to achieve. Again, I caution you with the strongest words: what you're doing is a bad idea. You should find another way.
Doc, it hurts when I do this.
Then don't do that!
The simpliest way (quick&dirty) is to put value within an array
int holder[] = new int[]{ a};
KillOver21(holder)
System.out.printf( "value=[%d]", holder[0] );
void KillOver21(int holder[] ) {
holder[0] = 0;
}

Serious generics issue: int vs. Integer java

for a long while, i have been trying to get a piece of code to work, and it just is not possible. the class i have requires a generic which i have set to Integer. so i tried the follwoing:
public class a<T> //set generics for this function
{
private T A;
protected boolean d;
public a(final T A)
{
this.A = A;
//do calculations
//since constructor cannot return a value, pass to another function.
this.d = retnData(Integer.parseInt(A.toString()) != 100); //convert to an integer, the backwards way.
}
private boolean retnData(boolean test)
{
return test;
}
}
// IN ANOTHER CLASS
transient a<Integer> b;
boolean c = b.d = b.a(25); // throws an erorr: (Int) is not apporpriate for a<Integer>.a
Java will not allow this since java sees that int != Integer, even though both accept the same data. and because of the way generics works i cannot set a b; because of the primitiveness of the type int. Even casting to an Integer does not work, as it still throws the "type error"
finnaly, i have to ask if there is some sort of work around for this, or is it futile to try and get this to work?
You are trying to explicitly call a constructor as an instance method. This cannot be done in Java.
Perhaps you want:
transient a<Integer> b = new a<Integer>(25);
boolean c = b.d;
However, since d is declared to be protected, that will only work if this code is in another class derived from a or in the same package.
Use
final a<Integer> b = new a<Integer>(10);
boolean c = b.d;
int can be explicitly converted to Integer with new Integer(10) or Integer.valueOf(10)
The code does not make much sense: b is an object of type a, which does not have an a method - so not sure what you expect from b.a(25);... This has nothing to do with int vs Integer...

How can I force Java to accept a conditional type for one of the parameters of a method call?

This question is hard to phrase, so I'm going to have to use some code samples. Basically, I have an (overloaded) method that takes 3 parameters, the last of which I overloaded. As in, sometimes the last parameter is a String, sometimes it's a double, etc. I want to call this method using a ternary conditional expression as the last parameter, so that depending on a certain value, it will pass either a double or a String. Here's an example...
Overloaded method headers:
writeToCell(int rowIndex, int colIndex, double value)
writeToCell(int rowIndex, int colIndex, String value)
What I'm trying to do:
writeToCell(2, 4, myValue != null ? someDouble : someString);
This, however, causes a compilation error:
The method writeToCell(int, int, double) in the type MyType is not applicable
for the arguments (int, int, Object&Comparable<?>&Serializable)
It seems that Java isn't "smart enough" (or just doesn't have the functionality built in on purpose) to realize that either option has a method that supports it. My question is - is there any way to do this? I know I can sort of simulate it by passing in the double as a String (e.g. writeToCell(2, 4, myValue != null ? someDouble.toString() : someString);), but the method needs to receive it as a double data type.
Logic tells me that there's no way to force Java to accept this statement... But it's worth a try, as it will result in a lot clearer code for me. Anyone know of a way to do this...?
Method calls are resolved statically, at compile time, not dynamically, at runtime. Therefore, the compiler is looking for the type that matches both of the possible arguments in that expression, as you can see.
You could do what the SDK does a lot of, and define your method as
writeToCell(int rowIndex, int colIndex, Object value)
and then have the first line be
final String repr = String.valueOf(value);
There are plenty of other solutions, but it's best not to overthink this.
Demonstration:
static class WrongAgain
{
void frob(final Object o)
{
System.out.println("frobo " + o);
}
void frob(final String s)
{
System.out.println("frobs " + s);
}
}
public static void main(final String[] args)
{
final WrongAgain wa = new WrongAgain();
wa.frob("foo");
Object o = "foo";
wa.frob(o);
}
If method lookup were dynamic, then the you'd see "frobs" both times. It's static.
Is there any particular reason not to just write it out?
if (myValue == null)
writeToCell(2, 4, someString);
else
writeToCell(2, 4, someDouble);
The return type from the ternary operation is being upcast to java.lang.Object, as the common superclass class of both String and the autoboxed double, so you would have to provide the method signature for the object, and then use that to make the appropriate cast and call the relevant method:
public class SoCast {
public static void main(String[] args) {
SoCast sc = new SoCast();
Double someDouble = 3.14;
String someString = "foo";
String myValue = null;
sc.writeToCell(2, 4, myValue != null ? someDouble : someString);
myValue = "hello";
sc.writeToCell(2, 4, myValue != null ? someDouble : someString);
}
private int writeToCell(int rowIndex, int colIndex, Object value) {
int result = -1;
if (value instanceof String) {
result = this.writeToCell(rowIndex, colIndex, (String) value);
} else if (value instanceof Double) {
result = this.writeToCell(rowIndex, colIndex, (Double) value);
}
return result;
}
private int writeToCell(int rowIndex, int colIndex, Double value) {
return 1;
}
private int writeToCell(int rowIndex, int colIndex, String value) {
return 5;
}
}
I suspect that it chokes up because the type of object (and hence overloaded version which should be called) cannot be determined at compile time. It's similar to:
Object o = myValue != null ? someDouble : someString;
writeToCell(2, 4, o);
Thanks everyone for all your suggestions and explanations.
A coworker of mine took a look at my code and suggested a solution that I implemented. I inserted the following code into the beginning of my double method:
if(value == null){
writeToCell(rowIndex, colIndex, someString)
}
else{
...method body...
}
I know that this implementation might not always be the best idea, but since I almost always need to check for null when passing a double value to this method, it makes the most sense in this situation. This way I don't have to repeat the check code (if / ternary statement) each time, and my method calls are much cleaner.
The ternary operator has to return the same type from the "then" or "else" clause. If you can deal with Double instead of double, then you could try
Object o = (myValue != null ? someDouble : someString);
writeToCell(2, 4, o);
and change the writeToCell method to accept arguments (int, int, Object).

Categories