I am trying to write a method in a class which could be invoked several times, each time modifying one of the class' fields. However, I need to new the object and set the field's value to it if I want to modify it, but if do this inside the method, the reference seem to be lost and the field left unchanged after the calling.
Public class A {
private Immutable a; //Immutable class
private Immutable b;
public void modify(Immutable k,int v) {
k=new Immutable(v); //Now I am trying to pass
//a and b as parameters but they remain unchanged
}
}
Is there any way to pass the name of the field into the method (e.g., change the method modify(Immutable k, int v) to modify(String kName, int v), then use the name of the field to access it?
Thanks for any inputs!
Java does not support Call-by-name or call-by-reference, only Call-by-value. Your k variable (the method parameter) is completely independent from any variable used outside of the class (if there was one at all).
You could use Reflection to support passing "a" or "b" (or a Field object), but you should not.
Better have two methods:
public void setA(int v) {
this.a = new Immutable(v);
}
public void setB(int v) {
this.b = new Immutable(v);
}
If it is more complicated than a single constructor call, factor the common part out to a common method.
If you need to access a variable by a String key, you should use a Map.
Map<String, Immutable> _vars = new HashMap<String, Immutable>();
public void modify(String key, int v) {
_vars.put(key, new Immutable(v);
}
What I understand is that you're trying to create a new Immutable given an integer (v). In your modify method right now, k is a temporary reference. Setting the value "k =" in here, only affects the reference stored here in this method, not whatever reference you called modify with.
You have client code like this currently:
A a = new A();
Immutable k = new Immutable(x);
a.modify(k, y);
and you're hoping that k will be changed. What you really want instead of the 3rd line is:
k = new Immutable(y);
Assuming that things are really more complicated, then I would need more information to help you further.
Use a value holder.
public class ValueHolder<T> {
private T value ;
public ValueHolder(T value) {
this.value = value ;
}
public T get() {
return value ;
}
public void set(T value) {
this.value = value;
}
public static <V> ValueHolder<V> make(V value) {
return new ValueHolder<V>(value);
}
}
public class Processor {
private Inmutable a ;
private Inmutable b ;
public void modify(ValueHolder<Inmutable> k, int v) {
k.set(new Inmutable(v));
}
}
Once that is done you can get the instance you just created from the value holder.
Processor processor = new Processor();
ValueHolder<Inmutable> holder = ValueHolder.make(k);
processor.modify(holder, value);
k = holder.get() ;
Related
I want to print function actual parameter name in function.
For reference please refer below code.Here i am trying reflection.
class Refrction
{
public static int a=12;
public static int b=12;
public static int c=13;
public void click(int x)
{
Class cls=Refrction.class;
Field[] fields = cls.getFields();
//here i want to print "a" if function actual parameter is "a" while calling the click function
//here i want to print "b" if function actual parameter is "b" while calling the click function
//here i want to print "c" if function actual parameter is "c" while calling the click function
}
}
public class Reflections extends Refrction
{
public static void main(String[] args)
{
Refrction ab=new Refrction();
ab.click(a);
ab.click(b);
ab.click(c);
}
}
Unless the values of a, b and c never changes (and you can deduce which variable was used as argument by looking at the value) this is not possible. You need to pass more information to the method.
One way would be to do
public void click(int x, String identifier) {
...
}
and call it with
ab.click(a, "a");
Or, you could wrap the values in a (possibly mutable) object, as follows:
class IntWrapper {
int value;
public IntWrapper(int value) {
this.value = value;
}
}
and then do
public static IntWrapper a = new IntWrapper(11);
and
public void click(IntWrapper wrapper) {
if (wrapper == a) {
...
}
...
}
I was testing whether you can change the value of the static variable x by passing it through a parameter, but I found out that you can't do it like that.
public class Test {
static int x;
static void changeX(int x_) {
x_ = 50;
}
public static void main(String args[]) {
changeX(x);
System.out.println(x);//it prints out zero because the static variable did not get changed
}
}
If we do it like this, we can change it:
public class Test {
static int x;
static void changeX(int x_) {
x = 50;
}
public static void main(String args[]) {
changeX(x);
System.out.println(x);
}
}
Which means you have to directly reference to the static variable in order to change it. Okay. Now. My question is, is there a way to change a class variable by just passing it through the parameter, without referencing it in the implementation? Basically, is there a way to use the first way somehow? Thanks.
You can achieve what you are asking, but you need to be aware of the subtle limitations. You can modify an object reference passed into a method, but you cannot reassign the reference in the method and have the original object be changed.
Java is always pass by value. Period.
Object references, are passed by value, but it is through those references (which point to the same memory location), that you can modify objects inside of methods, through the parameter.
You cannot modify primitives (int, float, boolean, etc) in this manner, they are always passed by value. You also cannot modify immutable objects (such as String), as they cannot be changed using a public interface.
Consider this simple example, which tests creating an object with some modifiable fields, by-value, and by-reference (it's modifying by object reference, that itself is passed by value):
public class ParameterPassingTest {
static SomeObject someStaticObject;
public static void main(String[] args) {
// initialize a static object reference
someStaticObject = new SomeObject("I am a static Object", 10);
System.out.println("My static object before: " + someStaticObject);
// try modifying the reference by value
modifySomeObjectByValue(someStaticObject);
// try printing the value, it will be the same
System.out.println("My static object after mod-by-value: " + someStaticObject);
// now, try modifying by object reference
modifySomeObjectByReference(someStaticObject);
// print again. new values should be observed
System.out.println("My static object after mod-by-reference: " + someStaticObject);
}
// this method tries to modify the original object by assigning directly to the method parameter. It won't work.
public static void modifySomeObjectByValue(SomeObject someObject) {
SomeObject newObject = new SomeObject("I am another object, from a local method", 20);
someObject = newObject; // try to modify the original object by assigning to the parameter directly
}
// this method tries to modify the original object by using the object's public interface. It works.
public static void modifySomeObjectByReference(SomeObject someObject) {
// try to modify the original object by using the reference passed in
someObject.setaString("I have been modified by a method");
someObject.setAnInt(50);
}
}
// simple, generic class object with some fields.
class SomeObject {
String aString;
int anInt;
public SomeObject(String aString, int anInt) {
this.aString = aString;
this.anInt = anInt;
}
public String getaString() {
return aString;
}
public void setaString(String aString) {
this.aString = aString;
}
public int getAnInt() {
return anInt;
}
public void setAnInt(int anInt) {
this.anInt = anInt;
}
#Override
public String toString() {
return "aString = " + getaString() + " | anInt = " + getAnInt();
}
}
This produces output:
My static object before: aString = I am a static Object | anInt = 10
My static object after mod-by-value: aString = I am a static Object | anInt = 10
My static object after mod-by-reference: aString = I have been modified by a method | anInt = 50
Java passes primitives always as value. Objects on the other hand are always passed as reference. In your second example, you access the static attribute x and not the parameter x_.
Furthermore, static does not protect an attribute from being rewritten. It binds an attribute to the class (without static attributes are bound to objects). Maybe you meant final?
EDIT: corrected a typo.
I want to write a method that only takes certain values for a parameter, like f.e. in the Toast class in Android. You can only use Toast.LENGTH_SHORT or Toast.LENGTH_LONG as duration for the method makeText(Context context, int resId, int duration). I had a look at the source code of the Toast class but found nothing there. How can I achieve that?
You can use #IntDef or #StringDef annotations for your methods like this:
#Retention(SOURCE)
#IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
public #interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
...
public abstract void setNavigationMode(#NavigationMode int mode);
#NavigationMode
public abstract int getNavigationMode();
Use an Enum Type, from the Java Tutorial,
An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.
As an example,
public enum MyEnum {
ONE, TWO;
}
public static void myMethod(MyEnum a) {
// a must be MyEnum.ONE or MyEnum.TWO (in this example)
}
Edit
To get String(s) from your enum types you can add field level values (which must be compile time constants) with something like,
public enum MyEnum {
ONE("uno"), TWO("dos");
MyEnum(String v) {
value = v;
}
private String value;
public String getValue() {
return value;
}
}
To use ints as is done with the Toast class, you can do something like this:
public class MyClass {
//by convention, constant names are all caps
public static final int VALUE_ONE = 0;
public static final int VALUE_TWO = 1;
public void myMethod(int value) throws InvalidParameterException {
if(value != VALUE_ONE || value != VALUE_TWO) {
throw new InvalidParameterException();
//or set default value instead of throwing an exception
}
else {
//your code
}
}
}
VALUE_ONE and VALUE_TWO are static and final, meaning that throughout the entire application there will only be one instance of that variable, and its value will never change (if you know C, it is similar to a #DEFINE). Thus, when someone passes MyClass.VALUE_ONE as an argument, you know exactly what it is, every time, while the caller doesn't necessarily need to know the integer value behind the constant. And then you will want to do a runtime check to make sure that what was passed in was one of the valid values, and if not, throw an exception. Or, if the value passed in isn't very critical, you could just set a default value if the argument is incorrect rather than throw an exception.
I have an object, obj, of type MyObject, that I declare an instance of.
MyObject obj;
However, I don't initialize it. MyObject's Class looks something like:
public class MyObject {
public String i;
public String j;
public MyObject(String i) {
i = this.i;
}
}
So now, I want to set the value of j. So I say:
obj.j = "Hello";
Can I do this without having initialized obj? i.e. without saying:
obj = new MyObject("My i");
Will this object be null if I were to check the value of it, if I don't initialize it, or is setting a field within it enough to make it not null?
Thanks!
No, you cannot do that. You will have to create a new instance of MyObject if you want to access its fields.
Unless you make the fields static, ofcourse.
Do note that having your fields public violates encapsulation. You should make them private (or protected, if it's appropriate) and use getters and setters to provide access.
Sidenote:
public MyObject(String i) {
i = this.i;
}
This will not do what you want.
You have to assign the parameter i to the field variable i, not the other way around.
public MyObject(String i) {
this.i = i;
}
I've been looking for the answer to this problem all day.
I have a value class that holds a variety of values as long as the program is running.
I create a new Value object in class A, and store an int value.
Class A also has a printMoney() method.
public class A {
Value value = new Value();
value.setMoney(100);
public void printMoney {
System.out.println(value.getMoney);
}
In class B, I want to be able to call printMoney() from class A, so logically I do the following:
public class B {
A a = new A();
a.printMoney();
}
This does, however, return '0' as a value instead of '100'.
I understand that by creating an A object, I automatically create a new value object, which has its default money value. So, basically my question is; how do I solve this?
Make the object static. static Value value = new Value();
static variables are shared across all the objects
So the change made in static variable will be reflected for all the objects of class.
if you want to get that value in A you have to assign the value in A construtor, like
public class A {
Value value = new Value();
public A() {
this.value.setMoney(100);
}
otherwise, you can make the value static
you should receive the instance that creates the object B and save it then you would be able to call it
like so:
public class A {
B b = new B(this);
}
public class B {
A a;
public B(A a) {
this.a = a;
}
private someMethod () {
a.printMoney();
}
}