LISTSERV mailing list manager LISTSERV 16.0

Help for TEAM-ADA Archives


TEAM-ADA Archives

TEAM-ADA Archives


TEAM-ADA@LISTSERV.ACM.ORG


View:

Message:

[

First

|

Previous

|

Next

|

Last

]

By Topic:

[

First

|

Previous

|

Next

|

Last

]

By Author:

[

First

|

Previous

|

Next

|

Last

]

Font:

Proportional Font

LISTSERV Archives

LISTSERV Archives

TEAM-ADA Home

TEAM-ADA Home

TEAM-ADA  September 2001

TEAM-ADA September 2001

Subject:

Elaboration of Java vs Ada Pro/Con

From:

[log in to unmask]

Reply-To:

[log in to unmask]

Date:

Wed, 5 Sep 2001 11:45:50 +1000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (352 lines)

This is a long post, but illustrates some of the Pros and Cons of Ada vs Java in a practical, industrial computing sense.

Executive Summary:
An example is shown of how something trivially easy in Ada can be a real bear in Java.
The same example shows the extensive technical support for Java that is available to overcome these difficulties, and should make all readers on this list ponder the fact that there's no Ada equivalent. (Typical example: How to parse XML into Ada, How to generate HTML in Ada, How to implement a TCP/IP stack in Ada etc)

I wrote in a previous post:
> Now I like Java. After Ada, it's my favourite language, and I often find myself wishing "gee, I wish Ada could do X as quickly and easily as I can with Java 1.whatever". (Of course just as often, I wish that Java of any variety could do Y at all, when Ada-95 does it trivially, and Java suffers from fatal flaws due to its C ancestry, and .... but that's beside the point).

Example of the type of thing I mean:

Java Solution -

From Latest JDC Tech Tips:
--------QUOTE START -------------------------

MAKING DEFENSIVE COPIES OF OBJECTS

Suppose that you are doing some graphical programming using the
Rectangle class in the AWT. In your program, a Rectangle object
is passed to a constructor for a class. The constructor checks
the width and height of the Rectangle to make sure that the
values are positive. If width and height are positive, then the
volume of the rectangle (width * height) is guaranteed to be
positive. In the program, you also take other steps to ensure
that objects of your class reference only valid Rectangles. For
example, you make the class final. In this way, no subclass can
invalidate the error checking you do in the program.

The code looks like this:

import java.awt.Rectangle;

final class TestRect {
private final Rectangle rect;

public TestRect(Rectangle r) {

// check for width/height at least 1

if (r.width < 1 || r.height < 1) {
throw new IllegalArgumentException();
}

rect = r;
}

public int getVolume() {
return rect.width * rect.height;
}
}

public class CopyDemo1 {
public static void main(String args[]) {

// create a Rectangle and a TestRect

Rectangle r = new Rectangle(0, 0, 5, 10);
TestRect t = new TestRect(r);

// set width to an invalid value and
// compute volume

//r.width = -59;
System.out.println("Volume = " +
t.getVolume());
}
}

So is this code foolproof? Can a bad Rectangle object somehow get
through the checks and be referenced from within TestRect code?
The answer is yes. If you uncomment the line in the CopyDemo1
program that reads "r.width = -59", and then run the program, the
result is:

Volume = -590

which is probably not what you had in mind. The problem is that
when you pass an object as an argument to a method, you're really
passing a reference (pointer) to the object. This means that a
single object can be shared across various parts of a program.
See the December 5, 2000 Tech Tip "Returning Multiple Values From
a Method" for a further explanation of how arguments are passed
to a method.

How can you fix the problem illustrated above? One way is to make
a copy of the Rectangle passed to TestRect:

import java.awt.Rectangle;

final class TestRect {
private final Rectangle rect;

public TestRect(Rectangle r) {

// use copy constructor to copy Rectangle
// object

rect = new Rectangle(r);

// check for valid width/height

if (rect.width < 1 || rect.height < 1) {
throw new IllegalArgumentException();
}
}

public int getVolume() {
return rect.width * rect.height;
}
}

public class CopyDemo2 {
public static void main(String args[]) {

// create Rectangle and TestRect objects

Rectangle r = new Rectangle(0, 0, 5, 10);
TestRect t = new TestRect(r);

// set width to an invalid value

r.width = -59;

// compute volume

System.out.println("Volume = " +
t.getVolume());
}
}

In this approach, you make a copy using the copy constructor for
Rectangle, the constructor that takes a Rectangle argument and
creates a new object with the same values. You make the copy
before validity checking. The validity checking is done on the
copy to avoid subtle problems in multi-threaded programs. One of
these subtle problems is the possibility that another thread
could change the passed-in argument after it has been checked but
before it has been copied.

If you run the CopyDemo2 program, the result is:

Volume = 50

Because you made a copy of the argument within the constructor,
changing the width to -59 outside of the constructor has no
effect on the result. Note that making copies in this way has
some cost in speed and space, especially if you copy big objects.

Another way to apparently solve this problem is to use a clone()
method. But this approach doesn't always work, as the following
example illustrates:

import java.awt.Rectangle;

final class TestRect {
private final Rectangle rect;

public TestRect(Rectangle r) {

// clone the Rectangle object

rect = (Rectangle)r.clone();

// check for valid width/height

if (rect.width < 1 || rect.height < 1) {
throw new IllegalArgumentException();
}
}

public int getVolume() {
return rect.width * rect.height;
}
}

// subclass of Rectangle with bogus clone() method

class MyRectangle extends Rectangle {
public MyRectangle(int x, int y, int w, int h) {
super(x, y, w, h);
}

public Object clone() {
return this;
}
}

public class CopyDemo3 {
public static void main(String args[]) {

// create MyRectangle and TestRect objects

Rectangle r = new MyRectangle(0, 0, 5, 10);
TestRect t = new TestRect(r);

// set width to an invalid value

r.width = -59;

// compute volume

System.out.println("Volume = " +
t.getVolume());
}
}

Rectangle is not a final class, so it can be subclassed. In this
example, the class MyRectangle is defined with a degenerate clone
method, one that simply returns a reference to the object being
cloned. A clone method like this could either be malicious or
just poorly written. In either case, you don't get the desired
result. The output of the CopyDemo3 program is the same as the
CopyDemo1 program:

Volume = -590

The problem of shared access to objects can show up in other
contexts. Suppose you add an accessor method to TestRect
that returns the Rectangle reference stored within the object.
A user can then change the object in an arbitrary way, and the
assumptions you made about the object's validity no longer hold.

Another way of fixing the problem is to pass the width and height
values as integers, and not pass in a Rectangle object reference.
In general, you can also fix the problem by making a class
immutable, that is, objects of the class cannot be changed after
creation. But Rectangle is mutable, and so you need to find
another way to solve the problem.

Another situation where you might want to make a defensive copy
is illustrated in the following program:

class TestNames {
public static final String names[] =
{"red", "green", "blue"};
}

public class CopyDemo4 {
public static void main(String args[]) {
TestNames.names[0] = "purple";
System.out.println(TestNames.names[0]);
}
}

The fact that the names array is final means that you can't
assign to it. But you can still change the value of a particular
array slot. When you run this program, you get the result:

purple

In other words, you have effectively overwritten what is supposed
to be a read-only array.

How do you solve this problem? One way is to copy the array using
clone, another is to create a read-only view of the array using
the Collections Framework. Here's an illustration that shows both
approaches:

import java.util.*;

final class TestNames {
private static final String names[] =
{"red", "green", "blue"};

// return a copy of the names array

public static String[] getNames() {
//return names;
return (String[])names.clone();
}

// return a read-only List view of the array

public static List getNamesList() {
return Collections.unmodifiableList(
Arrays.asList(names));
}
}

public class CopyDemo5 {
public static void main(String args[]) {

// attempt to modify names[0] and then
// print its value

TestNames.getNames()[0] = "purple";
System.out.println(TestNames.getNames()[0]);

// get names array as a read-only list and
// print the value in the first slot

List list = TestNames.getNamesList();
System.out.println(list.get(0));

// attempt to modify the read-only list

//list.set(0, "purple");
}
}

Notice that this program makes the names array private, and
defines an accessor method for it, getNames(). However, simply
going this far does not solve the problem. You can still change
the first slot in the array. So the program clones the array.
After the cloning, if you change the first slot of the array, it
only affects the copy. Of course, cloning a large array has
a speed and space cost attached to it.

Notice too the Collections Framework mechanisms used in the
program. Arrays.asList() creates a list backed by an array.
Collections.unmodifiableList then creates a read-only view of the
list. The array is not copied in this case, but instead a
read-only List view is built on top of it.

These solutions involve either a shallow copy or no copy of the
underlying array. If the array contains mutable objects, then
there is still a problem because errant user code can change the
value of an individual object within the array. In the CopyDemo5
program above, an array of strings is used, and String objects
are immutable.

The need for defensive copying also shows up in other contexts,
such as after an object has been deserialized, or when an object
is added to a Set or Map. For example, one of the properties of
a set is that it contains no duplicate elements. What if a
mutable object is added to a set, and then it later changes so
that equals() is true between that object and another one in the
set? At this point, the set is corrupt. To avoid this problem,
a defensive copy should have been made.

For more information about making defensive copies of objects,
see item 24 "Make defensive copies when needed" in "Effective
Java Programming Language Guide" by Joshua Bloch
(http://java.sun.com/docs/books/effective/).

----- QUOTE END -----------------

Ada Solution:

Use a non-access-type parameter of mode "in".

Thus:

TestRect(R : in Rectangle);

Discussion:

Parameters of mode "in" may be read, but not written to. They can be treated in most respects as constants. If the parameter is an access type, then the contents of the object being accessed may be changed by other tasks, but the access itself can't be, it still references the same object.

------------------------------------------------------

Top of Message | Previous Page | Permalink

Advanced Options


Options

Log In

Log In

Get Password

Get Password


Search Archives

Search Archives


Subscribe or Unsubscribe

Subscribe or Unsubscribe


Archives

December 2017
November 2017
October 2017
September 2017
June 2017
May 2017
April 2017
January 2017
December 2016
November 2016
October 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014
November 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013
October 2013
September 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
February 2012
January 2012
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
December 2010
November 2010
October 2010
September 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
February 2009
January 2009
December 2008
November 2008
October 2008
September 2008
August 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
December 2007
November 2007
October 2007
September 2007
June 2007
May 2007
March 2007
February 2007
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
December 2005
November 2005
October 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
March 2004
February 2004
January 2004
December 2003
November 2003
October 2003
September 2003
August 2003
July 2003
June 2003
May 2003
April 2003
March 2003
February 2003
January 2003
December 2002
November 2002
October 2002
September 2002
August 2002
July 2002
June 2002
May 2002
April 2002
March 2002
February 2002
December 2001
November 2001
October 2001
September 2001
August 2001
July 2001
June 2001
May 2001
April 2001
March 2001
February 2001
January 2001
December 2000
November 2000
October 2000
September 2000
August 2000
July 2000
June 2000
May 2000
April 2000
March 2000
February 2000
January 2000
December 1999
November 1999
October 1999
September 1999
August 1999
July 1999
June 1999
May 1999
April 1999
March 1999
February 1999
January 1999
December 1998
November 1998
October 1998
September 1998
August 1998
July 1998
June 1998
May 1998
April 1998
March 1998
February 1998
January 1998
December 1997
November 1997
October 1997
September 1997
August 1997
July 1997
June 1997
May 1997
April 1997
March 1997
February 1997
January 1997
December 1996
November 1996
October 1996

ATOM RSS1 RSS2



LISTSERV.ACM.ORG

Secured by F-Secure Anti-Virus CataList Email List Search Powered by the LISTSERV Email List Manager