An interview question

J

Jerry

Can anyone help me to answer the following interview question? Thanks!

1. Change the following code so an instance of Person is immutable
once created. Please note that citiesVisited is an array

and may require special consideration.



public class Person {

/** Name of the Person */

String name;

/** Cities he/she has visited */

String[] citiesVisited;

public Person(String n, String[] cities) {

name = n;

citiesVisited = cities;

}

/**

* Accessor for citiesVisited

* @return Returns the citiesVisited.

*/

public String[] getCitiesVisited() {

return citiesVisited;

}

/**

* Accessor for name

* @return Returns the name.

*/

public String getName() {

return name;

}

}
 
B

Bob

Jerry said:
Can anyone help me to answer the following interview question? Thanks!

If you mean job interview, then I recommend you don't bother.

Based on the other two questions you've posted, you don't know anything
about Java.

I have an SCJP certificate in Java, and even I don't apply for Java
jobs, because I know they will *roast* you in the interview.

They'll sit at least two people in the room to question you, and at
least one will be a technical staff member. If you don't know things
like this, they will eat you alive.
 
P

Patricia Shanahan

Jerry said:
Can anyone help me to answer the following interview
question? Thanks!

Sure. I've got a little spare time this week.
1. Change the following code so an instance of Person is
immutable once created. Please note that citiesVisited is
an array and may require special consideration.

The first thing to do is to understand the question. Try to
restate it in your own words.

Patricia
 
K

Kevin McMurtrie

Can anyone help me to answer the following interview question? Thanks!

1. Change the following code so an instance of Person is immutable
once created. Please note that citiesVisited is an array

and may require special consideration.

That's a really easy one. You're screwed. Maybe you should try
programing in Java before studying for the tests.
 
A

Adam Maass

Jerry said:
Can anyone help me to answer the following interview question? Thanks!

1. Change the following code so an instance of Person is immutable
once created. Please note that citiesVisited is an array

and may require special consideration.



public class Person {

/** Name of the Person */

String name;

/** Cities he/she has visited */

String[] citiesVisited;

public Person(String n, String[] cities) {

name = n;

citiesVisited = cities;

}

/**

* Accessor for citiesVisited

* @return Returns the citiesVisited.

*/

public String[] getCitiesVisited() {

return citiesVisited;

}

/**

* Accessor for name

* @return Returns the name.

*/

public String getName() {

return name;

}

}

Maybe you'll learn something from this.

public final class Person {
.....

private String name;
private String[] citiesVisited;
.....

public String[] getCitiesVisited() {
return (String[]) citiesVisited.clone();
}


The trick is to avoid exposing the innards of the class in such a way that
they could be changed.

Making the class "final" prohibits any subclasses. (No knowing what a random
subclass might do).

Making the attributes "private" prohibits any class but the current class
from manipulating them.

Returning a copy of the citiesVisited array in getCitiesVisited prohibits
code outside the class from getting a copy of the reference to the array
inside the class and thereby changing its contents.


Returning the name without doing a copy is OK because the String class is
immutable. Likewise, a deep copy of the citiesVisited array is unnecessary.


-- Adam Maass
 
K

Kevin McMurtrie

Adam Maass said:
Jerry said:
Can anyone help me to answer the following interview question? Thanks!

1. Change the following code so an instance of Person is immutable
once created. Please note that citiesVisited is an array

and may require special consideration.



public class Person {

/** Name of the Person */

String name;

/** Cities he/she has visited */

String[] citiesVisited;

public Person(String n, String[] cities) {

name = n;

citiesVisited = cities;

}

/**

* Accessor for citiesVisited

* @return Returns the citiesVisited.

*/

public String[] getCitiesVisited() {

return citiesVisited;

}

/**

* Accessor for name

* @return Returns the name.

*/

public String getName() {

return name;

}

}

Maybe you'll learn something from this.

public final class Person {
....

private String name;
private String[] citiesVisited;
....

public String[] getCitiesVisited() {
return (String[]) citiesVisited.clone();
}


The trick is to avoid exposing the innards of the class in such a way that
they could be changed.

Making the class "final" prohibits any subclasses. (No knowing what a random
subclass might do).

Making the attributes "private" prohibits any class but the current class
from manipulating them.

Returning a copy of the citiesVisited array in getCitiesVisited prohibits
code outside the class from getting a copy of the reference to the array
inside the class and thereby changing its contents.


Returning the name without doing a copy is OK because the String class is
immutable. Likewise, a deep copy of the citiesVisited array is unnecessary.


-- Adam Maass

You missed a very important one. No job for you.

Maybe you should study examples like String and the immutable Number
implementors.
 
S

steve

Jerry said:
Can anyone help me to answer the following interview question? Thanks!

1. Change the following code so an instance of Person is immutable
once created. Please note that citiesVisited is an array

and may require special consideration.



public class Person {

/** Name of the Person */

String name;

/** Cities he/she has visited */

String[] citiesVisited;

public Person(String n, String[] cities) {

name = n;

citiesVisited = cities;

}

/**

* Accessor for citiesVisited

* @return Returns the citiesVisited.

*/

public String[] getCitiesVisited() {

return citiesVisited;

}

/**

* Accessor for name

* @return Returns the name.

*/

public String getName() {

return name;

}

}

Maybe you'll learn something from this.

public final class Person {
....

private String name;
private String[] citiesVisited;
....

public String[] getCitiesVisited() {
return (String[]) citiesVisited.clone();
}


The trick is to avoid exposing the innards of the class in such a way that
they could be changed.

Making the class "final" prohibits any subclasses. (No knowing what a random
subclass might do).

Making the attributes "private" prohibits any class but the current class
from manipulating them.

Returning a copy of the citiesVisited array in getCitiesVisited prohibits
code outside the class from getting a copy of the reference to the array
inside the class and thereby changing its contents.


Returning the name without doing a copy is OK because the String class is
immutable. Likewise, a deep copy of the citiesVisited array is unnecessary.


-- Adam Maass

er some one ain't too smart.
you forgot about stopping "cloneable"

steve
 
R

Richard Wheeldon

But you do need to copy the array in the constructor.
Otherwise:

String[] citiesVisited = new String[] { "Amsterdam", "Paris" };
Person p = new Person("Fred", citiesVisited);
citiedVisisted[0] = "London";
er some one ain't too smart.
you forgot about stopping "cloneable"

Sorry. I don't get this. Can you please explain ?

Richard
 
S

steve

But you do need to copy the array in the constructor.
Otherwise:

String[] citiesVisited = new String[] { "Amsterdam", "Paris" };
Person p = new Person("Fred", citiesVisited);
citiedVisisted[0] = "London";
er some one ain't too smart.
you forgot about stopping "cloneable"

Sorry. I don't get this. Can you please explain ?

Richard

sorry should have said using reflection, but you can always try to get round
it by extending the class.

to really **** it up change it to this :


public class ImmutablePerson {

/** Name of the Person */

private final String name;

/** Cities he/she has visited */

private final String[] citiesVisited;

public ImmutablePerson(final String n, final String[] cities) {

this.name = new String (n);

this.citiesVisited =new String[]( cities);

}

/**

* Accessor for citiesVisited

* @return Returns the citiesVisited.

*/

public String[] getCitiesVisited() {

return new String[](citiesVisited);

}

/**

* Accessor for name

* @return Returns the name.

*/

public String getName() {

return new String (name);

}

}

now when it is initted the internal variables will be set in stone, you can
only init a final once.
making the variables private does not always make them immutable.
and passing in/out references to objects does not make them immutable.

now you cannot reflect it or extend it, and it generates new copies of the
variables, so now it is immutable.

and it should be fairly bomb proof.
 
R

Ross Bamford

steve said:
Returning the name without doing a copy is OK because the String class is
immutable. Likewise, a deep copy of the citiesVisited array is unnecessary.

But you do need to copy the array in the constructor.
Otherwise:

String[] citiesVisited = new String[] { "Amsterdam", "Paris" };
Person p = new Person("Fred", citiesVisited);
citiedVisisted[0] = "London";
er some one ain't too smart.
you forgot about stopping "cloneable"

Sorry. I don't get this. Can you please explain ?

Richard

sorry should have said using reflection, but you can always try to get round
it by extending the class.

to really **** it up change it to this :


public class ImmutablePerson {

/** Name of the Person */

private final String name;

/** Cities he/she has visited */

private final String[] citiesVisited;

public ImmutablePerson(final String n, final String[] cities) {

this.name = new String (n);

this.citiesVisited =new String[]( cities);

}

/**

* Accessor for citiesVisited

* @return Returns the citiesVisited.

*/

public String[] getCitiesVisited() {

return new String[](citiesVisited);

}

/**

* Accessor for name

* @return Returns the name.

*/

public String getName() {

return new String (name);

}

}

now when it is initted the internal variables will be set in stone, you can
only init a final once.
making the variables private does not always make them immutable.
and passing in/out references to objects does not make them immutable.

Absolutely it does, /all else being equal/. The facilities Reflection
provides to access these members are 'Over and above' and one should not
design to prevent such usage.

The whole point of the various modifiers is to allow us to design a
proper object-oriented system where certain things are made available
and other things are not. The fact that the JVM provides a 'back-door'
for those who would use it should not influence your design at all.

Too much code seems to come designed to be used outside normal OOP
practices these days. Design it to work right in it's own element, and
let someone else worry about working it in theirs.
now you cannot reflect it or extend it, and it generates new copies of the
variables, so now it is immutable.

and it should be fairly bomb proof.

Bomb proof? You do realise that you new String(n) call, for example,
actually reuses the byte array in most cases anyway. The private members
are all easily accessible via reflection given appropriate permissions,
and so on. None of this matters really - that's my point.

IMHO this kind of thing arises from poor definition of what 'protecting
implementation' really means. You're not trying to protect from other
malicious people - that is a function of some higher layer - but from
misinformed, incorrect, and unreliable usage.
 
S

steve

steve wrote:
Returning the name without doing a copy is OK because the String class
is
immutable. Likewise, a deep copy of the citiesVisited array is
unnecessary.

But you do need to copy the array in the constructor.
Otherwise:

String[] citiesVisited = new String[] { "Amsterdam", "Paris" };
Person p = new Person("Fred", citiesVisited);
citiedVisisted[0] = "London";

er some one ain't too smart.
you forgot about stopping "cloneable"

Sorry. I don't get this. Can you please explain ?

Richard

sorry should have said using reflection, but you can always try to get
round
it by extending the class.

to really **** it up change it to this :


public class ImmutablePerson {

/** Name of the Person */

private final String name;

/** Cities he/she has visited */

private final String[] citiesVisited;

public ImmutablePerson(final String n, final String[] cities) {

this.name = new String (n);

this.citiesVisited =new String[]( cities);

}

/**

* Accessor for citiesVisited

* @return Returns the citiesVisited.

*/

public String[] getCitiesVisited() {

return new String[](citiesVisited);

}

/**

* Accessor for name

* @return Returns the name.

*/

public String getName() {

return new String (name);

}

}

now when it is initted the internal variables will be set in stone, you can
only init a final once.
making the variables private does not always make them immutable.
and passing in/out references to objects does not make them immutable.

Absolutely it does, /all else being equal/. The facilities Reflection
provides to access these members are 'Over and above' and one should not
design to prevent such usage.

The whole point of the various modifiers is to allow us to design a
proper object-oriented system where certain things are made available
and other things are not. The fact that the JVM provides a 'back-door'
for those who would use it should not influence your design at all. i might not want a "back-door"

Too much code seems to come designed to be used outside normal OOP
practices these days. Design it to work right in it's own element, and
let someone else worry about working it in theirs.
now you cannot reflect it or extend it, and it generates new copies of the
variables, so now it is immutable.

and it should be fairly bomb proof.

Bomb proof? You do realise that you new String(n) call, for example,
actually reuses the byte array in most cases anyway.

strings are immutable.

The private members
are all easily accessible via reflection given appropriate permissions,
and so on. None of this matters really - that's my point.
they are accessible but not changeable. ( FINAL!!!!)
IMHO this kind of thing arises from poor definition of what 'protecting
implementation' really means. You're not trying to protect from other
malicious people - that is a function of some higher layer - but from
misinformed, incorrect, and unreliable usage.

you obviously show a poor understanding of the subject being discussed.
the overriding point is this



1. Change the following code so an instance of Person is immutable
once created, it does not state that it has to be GOOD "OO" design.



2. the =new String[]( cities);, was thrown in there for a response
provoker.

3. you state the private members are accessible, via reflection, yes they
ARE.

BUT YOU CANNOT CHANGE THEM ONCE THEY ARE INITTED, BECAUSE I MADE THEM FINAL.
if you only make them private, they CAN BE CHANGED.

also by the way , strings are immutable by design., that is they get a new
copy made each time.
in reality i DO NOT NEED TO DO =New String (x);
but for clarity i do.

actually the class can still be extended, even though i stated it could not.

also define 'malicious', say you are writing part of a banking security
routine?

the above code is a A LOT more stable, both from a usage and an extension
point of view, as well as maintenance.





consider the following:

public class notimmutable{
private final Point thevalue;
{
public notimmutable( final Point Value){
thevalue=value;

}
public Point getValue(){
return Value;

}
}

this looks immutable , but it is NOT. , even with the :
private final Point thevalue;
 
R

Ross Bamford

steve wrote:
Returning the name without doing a copy is OK because the String class
is
immutable. Likewise, a deep copy of the citiesVisited array is
unnecessary.

But you do need to copy the array in the constructor.
Otherwise:

String[] citiesVisited = new String[] { "Amsterdam", "Paris" };
Person p = new Person("Fred", citiesVisited);
citiedVisisted[0] = "London";

er some one ain't too smart.
you forgot about stopping "cloneable"

Sorry. I don't get this. Can you please explain ?

Richard

sorry should have said using reflection, but you can always try to get
round
it by extending the class.

to really **** it up change it to this :


public class ImmutablePerson {

/** Name of the Person */

private final String name;

/** Cities he/she has visited */

private final String[] citiesVisited;

public ImmutablePerson(final String n, final String[] cities) {

this.name = new String (n);

this.citiesVisited =new String[]( cities);

}

/**

* Accessor for citiesVisited

* @return Returns the citiesVisited.

*/

public String[] getCitiesVisited() {

return new String[](citiesVisited);

}

/**

* Accessor for name

* @return Returns the name.

*/

public String getName() {

return new String (name);

}

}

now when it is initted the internal variables will be set in stone, you can
only init a final once.
making the variables private does not always make them immutable.
and passing in/out references to objects does not make them immutable.

Absolutely it does, /all else being equal/. The facilities Reflection
provides to access these members are 'Over and above' and one should not
design to prevent such usage.

The whole point of the various modifiers is to allow us to design a
proper object-oriented system where certain things are made available
and other things are not. The fact that the JVM provides a 'back-door'
for those who would use it should not influence your design at all.

i might not want a "back-door"
Too much code seems to come designed to be used outside normal OOP
practices these days. Design it to work right in it's own element, and
let someone else worry about working it in theirs.


Bomb proof? You do realise that you new String(n) call, for example,
actually reuses the byte array in most cases anyway.

strings are immutable.

String Objects are. But that's not the point, you're protecting from
people who are using the /back door/, right? Someone who could outright
touch your bytes. Nothing is 'final' in RAM is it?
The private members
they are accessible but not changeable. ( FINAL!!!!)


you obviously show a poor understanding of the subject being discussed.
the overriding point is this



1. Change the following code so an instance of Person is immutable
once created, it does not state that it has to be GOOD "OO" design.

Neither does it state that you should consider 'external factors'. That
just comes across as trying to be clever.
2. the =new String[]( cities);, was thrown in there for a response
provoker.

3. you state the private members are accessible, via reflection, yes they
ARE.

BUT YOU CANNOT CHANGE THEM ONCE THEY ARE INITTED, BECAUSE I MADE THEM FINAL.
if you only make them private, they CAN BE CHANGED.

How is the end user going to call methods on your class? From the
interface? Protecting members and what not protects you from other Java
programmers. If I were to try to hack a banking system written in Java
do you honestly believe I'd play by it's rules? I'd be in C or similar,
grabbing the data I wanted from memory, not giving a flying **** whether
you say it's final, initialized, or what.
the above code is a A LOT more stable, both from a usage and an extension
point of view, as well as maintenance.
consider the following:

public class notimmutable{
private final Point thevalue;
{
public notimmutable( final Point Value){
thevalue=value;

}
public Point getValue(){
return Value;

}
}

this looks immutable , but it is NOT. , even with the :
private final Point thevalue;

From an extension point of view it doesn't matter a jot. Not unless, again,
it's done via the back door. See the theme? You're designing for exceptional
circumstances...

My point is that even your immutable class is not immutable, from the
point of view of those people who your changes are aimed at making it
immutable to. So what's the point?
 
L

Lee Fesperman

Ross said:
String Objects are. But that's not the point, you're protecting from
people who are using the /back door/, right? Someone who could outright
touch your bytes. Nothing is 'final' in RAM is it?

Most modern CPU's provide memory access protection, and Operating Systems use it to
prevent other processes from accessing your data.
 
R

Ross Bamford

Most modern CPU's provide memory access protection, and Operating Systems use it to
prevent other processes from accessing your data.

So write a kernel module. Nothing is impossible, especially not with a
machine made by a man. Surely this kind of security is aimed at other
programmers, so don't forget I have complete (including physical) access
to the machine. My point is that there is little point is 'going
overboard' with secure design. There's always ways around it that are
far beyond the remit of a software design.

Instead of trying to make sure no-one can call your
getSecretBankingSystemData method without permission (which, if you do
your job properly, is a ridiculous prospect anyway), consider how to
prevent security breaches that /could/ happen. Time spent bomb-proofing
software to the nth degree is almost always time wasted. Bomb proof your
damn systems instead.

As an aside, I should say that I'm not including applets and so forth in
this - the whole model there is based around untrusted code, which is
probably the only valid application of such security. Maybe it was the
applet example that started everyone doing this all the time?
 
L

Lee Fesperman

Ross said:
So write a kernel module. Nothing is impossible, especially not with a
machine made by a man. Surely this kind of security is aimed at other
programmers, so don't forget I have complete (including physical) access
to the machine. My point is that there is little point is 'going
overboard' with secure design. There's always ways around it that are
far beyond the remit of a software design.

What good would writing a kernel module do? Exactly how would you place this module in
the kernel on someone's system? You're claiming that secure operation is impossible.
 
R

Ross Bamford

What good would writing a kernel module do? Exactly how would you place this module in
the kernel on someone's system? You're claiming that secure operation is impossible.

No, this has gotten off track a bit. What I'm saying is that there are
many perfectly valid techniques that can be used as part of a larger
system to achieve secure operation. As I mentioned, the design of the
Applet API is a good example of this kind of thing. However, there is a
subtle distinction between such design, and what I call "Over protective
code", where instead of considering how your security intentions fit
into the wider system focus is placed instead on 'securing' the classes
and methods themselves.

While this does have uses, as demonstrated by vast swathes of the core
JDK, it is, IMHO, a bad thing as a general practice. Code that has been
made <quote>bomb proof</quote> does have it's place but it also tends to
be inflexible, opaque and lacking in reusability, especially when taken
outside it's intended context.

The Kernel Module was probably a bad example, but my point was that even
if you deploy every lock down you can there will always be ways around
it that can only be addressed with specific /combinations/ of those
locks. Take a banking system, for example, as was an earlier example on
the thread. I would expect to need root access to achieve that, so I
could install what I liked anyway, and pretty much do what I liked,
irrespective of the modifiers inside the JVM, which after all is just a
process on 'my' machine.

I can't imagine much hacking is done by reflection?
 
I

iksrazal

Furthermore, you have to be root to install a kernel module. My
thinking is that security planning only goes to the non-root level,
because after that, what's the point? Maybe chroot or something but
that's getting even further offtopic.

iksrazal
 
L

Lee Fesperman

Ross said:
No, this has gotten off track a bit.

Right, I just thought you were going off track.
I can't imagine much hacking is done by reflection?

A certain amount I'm sure. If this is an issue, you just need to install a security
manager.
 
S

steve

No, this has gotten off track a bit. What I'm saying is that there are
many perfectly valid techniques that can be used as part of a larger
system to achieve secure operation. As I mentioned, the design of the
Applet API is a good example of this kind of thing. However, there is a
subtle distinction between such design, and what I call "Over protective
code", where instead of considering how your security intentions fit
into the wider system focus is placed instead on 'securing' the classes
and methods themselves.

While this does have uses, as demonstrated by vast swathes of the core
JDK, it is, IMHO, a bad thing as a general practice. Code that has been
made <quote>bomb proof</quote> does have it's place but it also tends to
be inflexible, opaque and lacking in reusability, especially when taken
outside it's intended context.

The Kernel Module was probably a bad example, but my point was that even
if you deploy every lock down you can there will always be ways around
it that can only be addressed with specific /combinations/ of those
locks. Take a banking system, for example, as was an earlier example on
the thread. I would expect to need root access to achieve that, so I
could install what I liked anyway, and pretty much do what I liked,
irrespective of the modifiers inside the JVM, which after all is just a
process on 'my' machine.

I can't imagine much hacking is done by reflection?

Ross has any one ever told you , that you are a complete fucking moron?

this was an interview question , within the realm of java.

as for my programming methods, I don't give a **** , what you think.
do you know why?

Because this "interview Question" is actually taken from a book "hardcore
java", then some very minor mods have been made to the code.
then a complete analysis was made as to how to convert it to an immutable
object.
your actually arguing with the author of the book.

Obviously author of the book has stronger thought processes than you will
ever have.
He is also not prone to fantasize about atomic strikes , and alien hackers
and such like taking over his code.

perhaps if you get the time , you may be able to pop down to your local
library and take the time to look through the book.

you may even be able to learn something, that is if you are not to fucking
arrogant to think you know everything.


PLONK.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top