Solved

General visiblity question

Posted on 2004-09-15
11
216 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
Comment Utility
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
Comment Utility
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
Comment Utility
>> 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
 
LVL 37

Assisted Solution

by:zzynx
zzynx earned 75 total points
Comment Utility
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
Comment Utility
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
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 37

Expert Comment

by:zzynx
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
>> 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
Comment Utility
>> 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
Comment Utility
>> 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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

For customizing the look of your lightweight component and making it look lucid like it was made of glass. Or: how to make your component more Apple-ish ;) This tip assumes your component to be of rectangular shape and completely opaque. (COD…
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…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

772 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now