Question

In one method of my Java source code, the same block of code occurs many times:

<some code>
<some code>
<block of code>
<some code>
<block of code>
<some code>
<some code>
<some code>
<block of code>
<some code>
<some code>
<block of code>
<some code>
etc..

What this block of code does is it finds out what property of an object should be the target of the code to follow. More specifically, at the beginning of the block we have a string "Object.property", and the task of the code is to parse it so that it finds out what type of an object "Object" is, and what property of "Object" "property" is. When that is done, and the block is over, the execution continues to do something with said property of said object. The property could be used in a comparison, or something could be assigned to it.

Now, my problem is that I would like to tidy up the code a little bit by placing this block inside another method, which I then could call multiple times instead. Furthermore, if I ever would find a bug in this block, I wouldn't need to go through every occurence to fix it - just the one method.

So this is basically what I want to do:

<some code>
<some code>
property = parse();
<some code>
property = parse();
<some code>
<some code>
<some code>
property = parse();
<some code>
<some code>
property = parse();
<some code>
etc..

property parse(){
 <block of code>
 return property;
}

Now, thanks to Java not having any pointers I can't for example return a property that is an integer from this new method. A copy of that integer would be returned (a pass-by-value), and all the rest of my code would be dealing with is the local integer copy of a property, and not the property itself. This is fine of course if the property only is to be used in a comparison, but when the rest of my code want's to assign something to it, things don't work anymore.

Is there a smart and simple workaround, so that I could shorten my Java code, and when modifying it, I'd only need to modify one part of the code?

EDIT:

To give you some real code, the block of code could look like this, when it's not placed in a different method, after it has gotten a string named toParse (that for this examples sake could be "niceShirt.size"):

String[] parts = toParse.split('\\.');
if(pantsList.containsKey(parts[0])){
    if(parts[1] == "size") pantsList.get(parts[0]).size += 1;
    if(parts[1] == "daysWorn") pantsList.get(parts[0]).daysWorn += 1;
}
if(shirtsList.containsKey(parts[0])){
    if(parts[1] == "size") shirtsList.get(parts[0]).size += 1;
    if(parts[1] == "daysWorn") shirtsList.get(parts[0]).daysWorn += 1;
}
if(shoesList.containsKey(parts[0])){
    if(parts[1] == "size") shoesList.get(parts[0]).size += 1;
    if(parts[1] == "daysWorn") shoesList.get(parts[0]).daysWorn += 1;
}

Now as code like this occurs many times, I'd love to have a method like this:

String[] parts = toParse.split('\\.');
if(pantsList.containsKey(parts[0])){
    if(parts[1] == "size") return pantsList.get(parts[0]).size;
    if(parts[1] == "daysWorn") return pantsList.get(parts[0]).daysWorn;
}
if(shirtsList.containsKey(parts[0])){
    if(parts[1] == "size") return shirtsList.get(parts[0]).size;
    if(parts[1] == "daysWorn") return shirtsList.get(parts[0]).daysWorn;
}
if(shoesList.containsKey(parts[0])){
    if(parts[1] == "size") return shoesList.get(parts[0]).size;
    if(parts[1] == "daysWorn") return shoesList.get(parts[0]).daysWorn;
}

and all I'd need to do in the rest of my code would be:

parse(toParse) += 1;

..but this doesn't work since the parse(toParse) is now a copy, a return-by-value, so it would do nothing to the real property of the object.

I hope this helps clarify the problem?

Was it helpful?

Solution

You can wrap a getter and a setter in an object of an anonymous class implementing a simple interface:

interface PropertyInfo {
    Object get();
    void set(Object value);
}

The parse() method would return an implementation of this interface that knows how to do a get and also knows how to do a set operation, based on other data passed in from the caller:

private PropertyInfo parse(...) { // take some parameters
    // Find your getter and setter through reflection
    final Method getter = ...
    final Method setter = ...
    return new PropertyInfo() {
        public Object get() {
            // Use the getter
        }
        public void set(Object value) {
            // Use the setter
        }
    };
}

When you need to use the property in a condition, you'd use something like this:

PropertyInfo p = parse(...); // pass whatever needs to be parsed
if (p.get() == 123) ...

When you need to set the property, you'd be able to call it like this:

PropertyInfo p = parse(...); // pass whatever needs to be parsed
p.set(123);

OTHER TIPS

Make your method void and have the first argument be a "handle" object - a simple object that has an integer field. That object will be passed by value, but its value can be modified as much as you like.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top