0

THERE ARE ISSUES WTIH AN UNDERSTANDING OF Java IN THIS QUESTION. AS THE AUTHOR, I HAVE KEPT THE ORIGINAL QUESTION INTACT AS THE ANSWERS DO AN EXCELLENT JOB OF CLEARING UP THOSE ISSUES

Please, feel free to make changes to below question in order to improve its quality as a pedagogical tool


I have a JAVA class containing one method, the method receives an array object of integers (as you can see in the code); however, in JAVA, everything is pass[ed]-by-value - a well established fact, i.e. overwriting an object or primitive type passed as an argument cannot happen using a local scope object or p. type.

In other words, in order to change an object (primitive or reference) in Java, one must access the data member (or "attribute") directly or indirectly via a member function (or "method") that has the authority to change the attribute. Simply, the method must have an effect.

The other method for changing the value of an object is to return a value via a function and set the original object to the returned value.

Here is my code (and question to follow):

CODE FRAG. I:

public class BlockSort
{

    public static void sort(Block [] blocks)
    {
        boolean sorted = false;
        int length = blocks.length;

        while(!sorted)
        {
            sorted = true;

            for (int i = 1; i < length; i++)
            {
                if (blocks[i - 1].width > array[i].width)
                {
                    Block tempBlock = blocks[i - 1];
                    blocks[i - 1] = blocks[i];
                    blocks[i] = tempBlock;
                }
                else if ((blocks[i - 1].width == array[i].width) && (blocks[i - 1].length > array[i].length))
                {
                    Block tempBlock = blocks[i - 1];
                    blocks[i - 1] = blocks[i];
                    blocks[i] = tempBlock;
                }
            }

            length = length - 1;
    }

}

Essentially, in a very minimalistic sense, the above code functions the same way as this [NOTE: this statement is not true, see answers):

CODE FRAG. 2:

public myClass
{
    public void doesNothing(int someParameter)
    {
        someParameter = someParameter - 1;
    }
 }

So, here is my question: without a return type, any value passed to above code will not really do anything, correct? In other words, it has no way of modifying what's passed to it with any real clout (because any modifications are function scope).

Community
  • 1
  • 1
Thomas
  • 4,827
  • 5
  • 28
  • 60
  • If your method does not return a value nor interact with an external system nor changes the state of the program; what is it you intend on testing? – Jeroen Vannevel May 30 '14 at 17:13
  • That's what I thought. Essentially - _without changing what I have written (as it is to specification)_ - I am trying to test whether or not the passed array actually gets sorted by what is written (which I can do logically, but I have been asked to use a JUnit). – Thomas May 30 '14 at 17:14
  • That's different; now you're saying that you want to test the state. This has nothing to do with your second code sample. – Jeroen Vannevel May 30 '14 at 17:15
  • Is there a way to do that with JUnit, i.e. is there a good source to consult (the ones I have consulted assume the reader knows more than I do) – Thomas May 30 '14 at 17:17
  • To do what? It's still not clear what you want to do and it definitely doesn't help to put code in your question that isn't relevant to the problem. Do you want to test whether your array was sorted? If so: what are you confused about? – Jeroen Vannevel May 30 '14 at 17:18
  • It looks like some people have answered, below. I started out in C++, where everything is very explicit (not a lot going on in the background or hidden from view, so to speak). So, if I pass an object (in this case an array), and sort the elements of the object, the object itself is modified (the method doesn't need to contain a return type). That's what it sounds like people are saying. – Thomas May 30 '14 at 17:24
  • Yes, that's generally correct (it doesn't hold up for immutable types like `String` which you can't modify). In order to test if the sorting works you can pass it to the sorting function and then inspect the array (which will have been sorted). – Jeroen Vannevel May 30 '14 at 17:27
  • possible duplicate of [How to test void method with Junit testing tools?](http://stackoverflow.com/questions/1244541/how-to-test-void-method-with-junit-testing-tools) – Joe Jun 01 '14 at 09:56
  • Read the question, now, it's hopefully now not a duplicate - at least, not of that question. I should probably change the title of the question to accurately reflect the changes made to the content of the question as a result of the conversation and answers. – Thomas Jun 01 '14 at 13:13

5 Answers5

1

Java is pass-by-value, but objects and arrays are reference types. The array you pass into sort will be the same array you get out (that is, it'll be in the same place in memory), but the things inside the array may be different.

Sneftel
  • 34,359
  • 11
  • 60
  • 94
  • i.e. the method _does_ alter the content as the value behaves as a reference to an object and therefore no return is needed? – Thomas May 30 '14 at 17:27
1

The BlockSort.sort method does have an effect. It gets passed a reference to a Block [] by value. This does not mean it cannot change the array contents.

If you call it for example with BlockSort.sort(myArray) the variable myArray will on return point to the same array instance. But the content of the array may be changed.

Henry
  • 40,427
  • 6
  • 56
  • 72
1

I am maintaining that the fragment is not testable

You are absolutely right: changes to parameters of primitive and immutable types cannot be detected from the outside; nor should they be.

[the second code fragment] has no way of modifying what's passed to it

That is also true. Moreover, it may not be possible at all - consider this call:

mc.doesNothing(2*a*a + 3*b + c);

The value passed in to doesNothing is computed from three variables, so there is nothing in the caller that could be modified,

In your original code fragment int someParameter is local to the implementation of doesNothing method - in the same sense that local variables are invisible from outside of the method. Testing it does not make any more sense than "testing" changes to any other local variable of a method.

The other code fragment (CODE FRAG. I), however, is different, because Java arrays are neither primitive nor immutable:

public static void sort(Block [] blocks) {
    // Any change to the content of blocks will be visible to the caller
}

Therefore, the changes performed to the blocks array inside the method will be visible to the caller, in the same way that the callers would see changes to any other mutable object.

Dale Wilson
  • 8,374
  • 2
  • 27
  • 47
Sergey Kalinichenko
  • 675,664
  • 71
  • 998
  • 1,399
  • Your answer is correct; however, I changed the above question (because I think I got mixed up). So, for the first question, I think your answer is right, but for the second, maybe not. I just don't want you to get down voted for my mistake. – Thomas May 30 '14 at 17:25
1

what I am asking ultimately is whether or not the above code is testable

Yes, it is. The code you've posted moves elements around inside the blocks array, and you can certainly test whether the items are sorted once the method returns

Block[] blocks = createBlocks();
BlockSort.sort(blocks);
for(int i = 1; i < blocks.length; i++) {
  assert blocks[i].width < blocks[i-1].width;
}
Ian Roberts
  • 114,808
  • 15
  • 157
  • 175
0

Okay, so, I am going to amalgamate the answers written in response to the original question (because there are a lot of good fragments of information in all of the responses that need to be put together).

THREE ISSUES ARE PRESENT


ISSUE no. 1 Pass-by-value or Pass-by-Reference

Essentially, the above question stems from a - seemingly pervasive - lack of understanding or confusion surrounding how Java's pass-by-value works. Objects in Java are indeed pass[ed]-by-value; however, what is passed by value is the reference to the object, i.e. the value behaves somewhat like a pointer in C++ (that may be untrue, but it seems that way). So, the argument received by the parameter is in fact a value, but the value contains - in thought - a reference to the object:

public static void sort(Block [] blocks)
{
    // CODE
}

This is not the case for primitive types. Primitive types pass a copy of their value to the parameter, so they are pass-by-value:

public void doesNothing(int someParameter)
{
    // CODE
} 

ISSUE no. 2: Arrays Are a Reference Type

An array is a reference type object in Java (as it is in other languages); therefore, when an array is passed, no return statement is need to modify its content. Integers - int are primitive type.

ISSUE no. 3: The Two Code Fragments In the Initial Questions (re-posted)

The two code fragments are indeed behaving differently. The first fragment is passing around values referring to a reference type. The second fragment is passing around values (or copies of values) of primitive type.

Therefore, the first code fragment has an effect, while the second does not

Thomas
  • 4,827
  • 5
  • 28
  • 60