Solved

General visiblity question

Posted on 2004-09-15
11
242 Views
Last Modified: 2010-03-31
Could somebody please clarify each of the following questions (?? … ??) for me - i'll use some code as an example! :)

private void addTimeSpan(Element from, Element to)
    {
      int type = -1, period = -1, day = -1, less = -1;
      Date date = null;
      long dateEpoch = -1; // form date has been saved in XML file
      MomentInTime fromMoment, toMoment;
     
      /** FROM **/
      // get all these variable values as strings
      String typeStr = from.getAttributeValue("type"),
      periodStr = from.getAttributeValue("period"),
      dayStr = from.getAttributeValue("day"),
      lessStr = from.getAttributeValue("less"),
      dateStr = from.getAttributeValue("date");
     
      if(typeStr != null)
        type = Integer.parseInt(typeStr.trim());
      if(periodStr != null)
        period = Integer.parseInt(periodStr.trim());
      if(dayStr != null)
        day = Integer.parseInt(dayStr.trim());
      if(lessStr != null)
        less = Integer.parseInt(lessStr.trim());
      if(dateStr != null)
        date = new Date(Long.parseLong(dateStr.trim()));
     
      fromMoment = new MomentInTime(type, period, day, less, date);
    }

So now I have to repeat for:
/** TO **/

suppose I made a method:
private void setAttributes(Element e, String period, String day …)

for /** FROM **/
call   setAttributes(from, periodStr, dayStr …)
?? will these strings now be set correctly in the addTimeSpan method ??
then   fromMoment = new MomentInTime(type, period, day, less, date);

for /** TO **/
call   setAttributes(to, periodStr, dayStr …)
?? will the fromMoment object now be altered (because using same String objects) ??

Also am I correct in saying if my method was:
private void setAttributes(Element e, int period, int day …)
?? then the values will NOT be set in addTimeSpan because types are primitive ??

And does the date object pose any similar problems.

I suppose an excellent and much appreciated answer to this wordy question would be the code re-written as efficiently as possible with an explanation of why things will or will not work a certain way!

Kindest regards,
Cathal.
0
Comment
Question by:cathalmchale
  • 7
  • 2
  • 2
11 Comments
 
LVL 16

Accepted Solution

by:
imladris earned 50 total points
ID: 12065242
The variable typeStr is declared in the addTimeSpan method. This means that typeStr is a reference to a String object. The call to getAttributeValue returns a reference to a String object which is then assigned to typeStr and all is well.

However, if you were to use a setAttributes call you would be facing a difficulty. The difficulty lies with the way that arguments are passed to methods. In Java (and most modern languages) arguments are passed "by value". This means that a *copy* of the argument is put on the stack, and the method uses this copy as the argument. The advantage of this tactic is that the callers variables are "safe" from sideeffects caused by the method. When you're reading the code, and you see a method being called, you cannot see what might be happening in the method. Calling by value helps the reader by encouraging that indeed, usually, nothing *does* happen.
So, since a copy goes to the method, assigning some value to that copy inside the method will not change the value of the variable you passed in.

This is true for Objects (String's in this case) as well as primitives.
0
 
LVL 16

Assisted Solution

by:imladris
imladris earned 50 total points
ID: 12065298
The main dodge to this (there's always a dodge) is as follows.

If you pass a reference to an object into a method, and the method changes the *object*, then the caller will see the changed object as well.

Why?

Well, if you have an object Foo, and pass a reference to it, a *copy* of the reference is passed into the method on the stack. But that copied reference is pointing to the *same* object. So if the method changes the object (calls some method of the object that changes its internal state, or, perhaps, directly changes one of its member variables), then the caller (still having a reference to that same object) will see that object in its new state.

On the other hand, remember that this does *not* work for Strings. Strings are immutable. A String object can't be changed; by anybody. You can only create new ones.
0
 
LVL 37

Expert Comment

by:zzynx
ID: 12065436
>> am I correct in saying if my method was:
>> private void setAttributes(Element e, int period, int day …)
>> ?? then the values will NOT be set in addTimeSpan because types are primitive ??
Yes.

>> for /** FROM **/
>> call   setAttributes(from, periodStr, dayStr …)
>> ?? will these strings now be set correctly in the addTimeSpan method ?
No, since String is an immutable object


>> And does the date object pose any similar problems
No. You can alter a Date or any other object (cf. MyData in what follows)


Run this little demo app:

/*
 * RefDemo.java
 *
 */

/**
 *
 * @author  zzynx
 */

public class RefDemo {
   
    public RefDemo() {
    }
   
    public void setString(MyData inputData, String key) {
        key = inputData.getKey();
    }

    public void setKeyOfMyData(MyData inputData, String key) {
        inputData.setKey(key);
    }

   
    public static void main(String arg[]) {
        RefDemo d = new RefDemo();
       
        String key = "First content";
        System.out.println("Key = " + key);
        d.setString( new MyData("2nd Key", "value 2"), key);
        System.out.println("Key = " + key);
       
        MyData data = new MyData("Key", "value");
        System.out.println("Data = " + data.toString());
        d.setKeyOfMyData(data, "new Key");
        System.out.println("Data = " + data.toString());
    }
   
    public static class MyData {
        private String key;
        private String value;
        public MyData(String key, String value) {
            this.key = key;
            this.value = value;
        }
        public String getKey() { return key; }
        public String getValue() { return value; }
        public void setKey(String key) {
            this.key = key;
        }
        public void setValue(String value) {
            this.value = value;
        }
        public String toString() {
            return "key =" + key + " - value = " + value;
        }
    }
}

Output:

Key = First content
Key = First content                                // <<< the String is not altered
Data = key =Key - value = value
Data = key =new Key - value = value   // <<< the MyData object IS altered
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LVL 37

Assisted Solution

by:zzynx
zzynx earned 75 total points
ID: 12065578
So, what could you do?

Make a

public class MyData {

      private int type = -1;
      private int period = -1;
      private int day = -1;
      private int less = -1;
      private Date date = null;

      // constructor(s)
      ...

      // setters
      ...

      // getters
      ...
}

private void addTimeSpan(Element from, Element to) {

    MyData data = new MyData();

    /** FROM **/
    setAttributes(from, data);  // This alters the fields of the MyData object 'data'
    fromMoment = new MomentInTime(data.getType(), data.getPeriod(), data.getDay(), data.getLess(), data.getDate());

    /** TO **/
    setAttributes(to, data);  // This alters the fields of the MyData object 'data' again
    toMoment = new MomentInTime(data.getType(), data.getPeriod(), data.getDay(), data.getLess(), data.getDate());
}
0
 
LVL 37

Expert Comment

by:zzynx
ID: 12065665
Even better
(since more object oriented; it's the MyData object that "imports" the data from an Element object)
is this:


public class MyData {

      private int type = -1;
      private int period = -1;
      private int day = -1;
      private int less = -1;
      private Date date = null;

      // constructor(s)
      ...

      // setters
      ...

      // getters
      ...

     public void importData(Element e) {
           String typeStr = from.getAttributeValue("type"),
           String periodStr = from.getAttributeValue("period"),
           String dayStr = from.getAttributeValue("day"),
           String lessStr = from.getAttributeValue("less"),
           String dateStr = from.getAttributeValue("date");
     
           if(typeStr != null)
               type = Integer.parseInt(typeStr.trim());
           if(periodStr != null)
              period = Integer.parseInt(periodStr.trim());
          if(dayStr != null)
              day = Integer.parseInt(dayStr.trim());
          if(lessStr != null)
              less = Integer.parseInt(lessStr.trim());
          if(dateStr != null)
             date = new Date(Long.parseLong(dateStr.trim()));
     }
}

private void addTimeSpan(Element from, Element to) {

    MyData data = new MyData();

    /** FROM **/
    data.importData(from);  // This alters the fields of the MyData object 'data'
    fromMoment = new MomentInTime(data.getType(), data.getPeriod(), data.getDay(), data.getLess(), data.getDate());

    /** TO **/
    data.import(to);  // This alters the fields of the MyData object 'data' again
    toMoment = new MomentInTime(data.getType(), data.getPeriod(), data.getDay(), data.getLess(), data.getDate());

}
0
 
LVL 37

Expert Comment

by:zzynx
ID: 12065693
Typo: in the importData() function replace all occurrences of 'from' into 'e'


      public void importData(Element e) {
           String typeStr = e.getAttributeValue("type"),
           String periodStr = e.getAttributeValue("period"),
           String dayStr = e.getAttributeValue("day"),
           String lessStr = e.getAttributeValue("less"),
           String dateStr = e.getAttributeValue("date");
     
           if(typeStr != null)
               type = Integer.parseInt(typeStr.trim());
           if(periodStr != null)
              period = Integer.parseInt(periodStr.trim());
          if(dayStr != null)
              day = Integer.parseInt(dayStr.trim());
          if(lessStr != null)
              less = Integer.parseInt(lessStr.trim());
          if(dateStr != null)
             date = new Date(Long.parseLong(dateStr.trim()));
     }
0
 

Author Comment

by:cathalmchale
ID: 12066155
Thanks for the info guys, its good to know exactly whats going on so I hopefully wont make the same mistakes again and again ... and again.
I guess the only problem with such a solution zzynx is that it adds to the lines of code greatly - and if your class is already quite full...!
Perhaps here is an alternative:  (again thanks, ill accept now)

/**
     * @param from Element to be converted to MomentInTime
     * @param to Element to be converted to MomentInTime
     */
    private void addTimeSpan(Element from, Element to)
    {
      MomentInTime fromMoment = createMoment(from);
      MomentInTime toMoment = createMoment(to);
     
      timeSpans.add(new TimeSpan(fromMoment, toMoment));
    }


    /** Helper method for addTimeSpan
     * @param e Element to be converted to MomentInTime
     * @return the initialised MomentInTime object
     */
    private MomentInTime createMoment(Element e)
    {
      MomentInTime moment = new MomentInTime();
      int type = -1, period = -1, day = -1, less = -1;
      Date date = null;
     
      // get all these variable values as strings
      String typeStr = e.getAttributeValue("type"),
      periodStr = e.getAttributeValue("period"),
      dayStr = e.getAttributeValue("day"),
      lessStr = e.getAttributeValue("less"),
      dateStr = e.getAttributeValue("date");
      // initialise variables with these values
      if(typeStr != null)
        type = Integer.parseInt(typeStr.trim());
      if(periodStr != null)
        period = Integer.parseInt(periodStr.trim());
      if(dayStr != null)
        day = Integer.parseInt(dayStr.trim());
      if(lessStr != null)
        less = Integer.parseInt(lessStr.trim());
      if(dateStr != null)
        date = new Date(Long.parseLong(dateStr.trim()));
       
      // return the MomentInTime object
      moment.setMoment(type, period, day, less, date);
      return moment;
    }
0
 
LVL 37

Expert Comment

by:zzynx
ID: 12066247
Thanks for accepting

>> the only problem with such a solution zzynx is that it adds to the lines of code greatly
I definitely disagree on that!
Java is all about lots of small classes. What's the problem with one extra MyData class?

>> and if your class is already quite full...!
...then it's time to rethink the design and split it up in smaller parts
0
 
LVL 37

Expert Comment

by:zzynx
ID: 12066282
>> Perhaps here is an alternative
Mmmm.
Only wonder why you don't make a MomentInTime constructor that accepts Element as parameter.
A function that is called createXXXX() begs for being replaced by a constructor, no?
0
 

Author Comment

by:cathalmchale
ID: 12066323
>> and if your class is already quite full...!
...then it's time to rethink the design and split it up in smaller parts


yea sometimes but when your working on a complex swing gui - panels, models etc. can grow rapidly - its nice to use inner classes so that belonging units are contained but this can sometimes reduce readability greatly etc. bla bla...
0
 
LVL 37

Expert Comment

by:zzynx
ID: 12066372
>> yea sometimes but when your working on a complex swing gui
I do
>> its nice to use inner classes
I don't ;°)
>> so that belonging units are contained
I try to use sub packages with clear names: models, renderers, decorators, ...
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Protect jar file - windows app 2 64
jar file executable 12 58
Android development question 2 51
Java syntax, or is it Selenium 6 30
For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…

791 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question