Solved

General visiblity question

Posted on 2004-09-15
11
255 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

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

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
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…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…

724 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