For Programmers: Free Programming Magazines  


Home > Archive > Java Help > October 2004 > private access to arrays









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author private access to arrays
Bill Lawson

2004-10-26, 3:59 pm

I am writing a program which uses an array of bytes (declared using the
private key word). My understanding of the word "private" means that the
data should not be able to be changed by any other objects (unless the
change is made via a setter method). However, the following test program
illustrates that this is not the case - an element in my private array
(declared in PrivateClass)was changed by the Test class and yet PrivateClass
does not have a setter method. Is this a bug in the JVM and is there a way
of making sure that data in an array could not be accidently changed ? The
following uses 2 classes (Test and PrivateClass) to illustrates my point.

public class Test {
public Test()
{}
public static void main(String[] args)
{
PrivateClass pc = new PrivateClass();
byte[] localarray = pc.getdata();
System.out.println("Before: localarray byte 0 = " + localarray[0]);
System.out.println("Before: private array byte 0 = " + pc.getdata()[0]);
// this is the important bit - make the change
localarray[0] = 2; // this line changes private data which I find
rather naughty
// now both arrays (including the private array) have changed.
System.out.println("After: localarray byte 0 = " + localarray[0]);
System.out.println("After: private array byte 0 = " + pc.getdata()[0]);
}
}

class PrivateClass {
// set up private test array with every byte a 1
private byte[] data = {1, 1, 1, 1, 1};
public void PrivateClass() {}

public byte[] getdata()
{
return data;
}
}




Paul Lutus

2004-10-26, 3:59 pm

Bill Lawson wrote:

> I am writing a program which uses an array of bytes (declared using the
> private key word). My understanding of the word "private" means that the
> data should not be able to be changed by any other objects (unless the
> change is made via a setter method). However, the following test program
> illustrates that this is not the case - an element in my private array
> (declared in PrivateClass)was changed by the Test class and yet
> PrivateClass does not have a setter method. Is this a bug in the JVM and
> is there a way
> of making sure that data in an array could not be accidently changed ?


You have created a byte array in your private class, and you have a
reference to it called "data". Only the reference "data" is private. If you
can obtain a new reference to the actual byte array, then you can change
the data. Your method provides this reference.

Obviously the solution is to provide getter/setter methods that accept an
index into the array, rather than providing a reference to the original
array:

****************************************
******************************

public class Test {

public static void main(String[] args)
{
PrivateClass pc = new PrivateClass();
byte[] localarray = {3, 3, 3, 3, 3};
System.out.println("Before: localarray byte 0 = "
+ localarray[0]);
System.out.println("Before: private array byte 0 = "
+ pc.getData(0));
localarray[0] = 2;
System.out.println("After 1: localarray byte 0 = "
+ localarray[0]);
System.out.println("After 1: private array byte 0 = "
+ pc.getData(0));
pc.setData(0,(byte)2);
System.out.println("After 2: localarray byte 0 = "
+ localarray[0]);
System.out.println("After 2: private array byte 0 = "
+ pc.getData(0));
}
}

class PrivateClass {
private byte[] data = {1, 1, 1, 1, 1};

public byte getData(int index)
{
return data[index];
}

public void setData(int index,byte v)
{
data[index] = v;
}
}

--
Paul Lutus
http://www.arachnoid.com

Yogo

2004-10-26, 3:59 pm

"Bill Lawson" wrote:
>I am writing a program which uses an array of bytes (declared using the
> private key word). My understanding of the word "private" means that the
> data should not be able to be changed by any other objects (unless the
> change is made via a setter method). However, the following test program
> illustrates that this is not the case - an element in my private array
> (declared in PrivateClass)was changed by the Test class and yet
> PrivateClass
> does not have a setter method. Is this a bug in the JVM and is there a way
> of making sure that data in an array could not be accidently changed ?
> The
> following uses 2 classes (Test and PrivateClass) to illustrates my point.
>
> public class Test {
> public Test()
> {}
> public static void main(String[] args)
> {
> PrivateClass pc = new PrivateClass();
> byte[] localarray = pc.getdata();
> System.out.println("Before: localarray byte 0 = " + localarray[0]);
> System.out.println("Before: private array byte 0 = " +
> pc.getdata()[0]);
> // this is the important bit - make the change
> localarray[0] = 2; // this line changes private data which I find
> rather naughty
> // now both arrays (including the private array) have changed.
> System.out.println("After: localarray byte 0 = " + localarray[0]);
> System.out.println("After: private array byte 0 = " + pc.getdata()[0]);
> }
> }
>
> class PrivateClass {
> // set up private test array with every byte a 1
> private byte[] data = {1, 1, 1, 1, 1};
> public void PrivateClass() {}
>
> public byte[] getdata()
> {
> return data;
> }
> }
>


You can change the values of the array because an array is a mutable object
and your method returns a reference to it. You must return a copy of it in
order to be sure the original values won't be changed.

If you have for example a private Integer and you return a reference to it.
The value of the (original) Integer object can't be changed because an
Integer is immutable. An Integer doesn't have any method that will change
its internal value. An array is like a class having a method to set its
values.


Yogo


Bill Lawson

2004-10-27, 3:58 am

Xref: number1.nntp.dca.giganews.com comp.lang.java.help:254467

>
> You can change the values of the array because an array is a mutable

object
> and your method returns a reference to it. You must return a copy of it in
> order to be sure the original values won't be changed.
>
> If you have for example a private Integer and you return a reference to

it.
> The value of the (original) Integer object can't be changed because an
> Integer is immutable. An Integer doesn't have any method that will change
> its internal value. An array is like a class having a method to set its
> values.
>
>
> Yogo
>

Yes, thanks for that. I seem to remember reading about mutable and
immutable somewhere but could not remember what the hell they were. I fixed
my issue by (as u suggested) making a copy of the array, thus my getdata
method becomes:

public byte[] getdata()
{
byte [] temp = new byte[data.length];
for (int i = 0; i< data.length; i++)
{
temp[i] = data[i];
}
return temp;
}


Stefan Schulz

2004-10-27, 3:58 am

On Tue, 26 Oct 2004 21:56:43 +0100, Bill Lawson <bill@lawson123x.com>
wrote:

> object
> it.
> Yes, thanks for that. I seem to remember reading about mutable and
> immutable somewhere but could not remember what the hell they were. I
> fixed
> my issue by (as u suggested) making a copy of the array, thus my getdata
> method becomes:
>
> public byte[] getdata()
> {
> byte [] temp = new byte[data.length];
> for (int i = 0; i< data.length; i++)
> {
> temp[i] = data[i];
> }
> return temp;
> }


Why such an expensive copy?

Why not a classical getter?

public byte getData(int offset) {
return data[offset];
}



--

Whom the gods wish to destroy they first call promising.
Thomas G. Marshall

2004-10-27, 3:58 am

Bill Lawson coughed up:
> Yes, thanks for that. I seem to remember reading about mutable and
> immutable somewhere but could not remember what the hell they were.
> I fixed my issue by (as u suggested) making a copy of the array,
> thus my getdata method becomes:
>
> public byte[] getdata()
> {
> byte [] temp = new byte[data.length];
> for (int i = 0; i< data.length; i++)
> {
> temp[i] = data[i];
> }
> return temp;
> }


WHOA. Hold on. Don't do that.

*First off*, if you're intent on copying arrays, use two /other/ approaches.

clone()
or
System.arraycopy()

Both of which are far faster than what you're intending. System.arraycopy()
is a native routine, and hence optimized at the lowest (possible) level for
array copying. The copy is a shallow copy: each element is copied, but if
an element is another array or other object, only the reference of that
element object is copied, no recursive descent "deep copy" is made.

clone() will indeed create a new array object, with a similarly shallow
clone.

*Secondly*, provide a better accessor method is the usual standard
(/cleaner/) way to provide access to an otherwise opaque object's internals.


--
Framsticks. 3D Artificial Life evolution. You can see the creatures
that evolve and how they interact, hunt, swim, etc. (Unaffiliated with
me). http://www.frams.alife.pl/


Yogo

2004-10-27, 8:57 am

"Thomas G. Marshall" wrote:
....[color=darkred]
>
>

....
> *Secondly*, provide a better accessor method is the usual standard
> (/cleaner/) way to provide access to an otherwise opaque object's
> internals.
>



What would be a better getter method if you need the whole array (except for
the way the array is copied)?

If you have only a getter method returning one element at a time and you
need the whole array: you'll have to call the getter method for each element
and rebuild the array. This is not efficient at all.



Yogo




Stefan Schulz

2004-10-27, 8:57 am

On Wed, 27 Oct 2004 11:56:53 +0200, Yogo <n o s p a m> wrote:

> What would be a better getter method if you need the whole array (except
> for
> the way the array is copied)?
>
> If you have only a getter method returning one element at a time and you
> need the whole array: you'll have to call the getter method for each
> element
> and rebuild the array. This is not efficient at all.


In that case, yes. However, i very rarely encounter that situation. Usually
you will either want a variable-sized storage object (and thus, some kind
of
Collection), or read-only access is enough, in which a getter is fine
(usually
the JIT will inline the field read access anyway)

--

Whom the gods wish to destroy they first call promising.
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com