Results 1 to 7 of 7
  1. #1
    meringue is offline Member
    Join Date
    Mar 2009
    Posts
    3
    Rep Power
    0

    Default Accessing instance outside of creation method

    Hi all,
    This is my first post. Please forgive me if this sounds ridiculous; I've scoured forums, tutorials and even textbooks, and I think my brain has Java-shaped holes in it because I can't figure this out. This is my problem:

    How can I access an instance outside of the method that creates it (ie, access it in the main method in my example below)? Is it possible? I'm guessing it's a question of scope, but beyond that I'm at a loss.

    Here is a simple example of what I mean:
    Java Code:
    class Testing
    {
    public static void main(String[] args)
    {
        String gender = "Male";
        testy1(gender);
        System.out.println("Designation: "+testperson.designat);  
    /*This doesn't work. What can I do to access testperson here?*/
    }
        
        public static void testy1(String gender)
        {
        if (gender.equals("Male"))
          {
          Male testperson = new Male();
          testperson.setMale("Test Subject Male");
          System.out.println("Designation: "+testperson.designat);  
          }
        else if (gender.equals("Female"))
          {
          Female testperson = new Female();
          testperson.setFemale("Test Subject Female");
          System.out.println("Designation: "+testperson.designat);
          }  
        }
    
    }
    Also, how could I access testperson, and its methods, in other non-main methods?
    Help very much appreciated.
    Thanks.

  2. #2
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,565
    Rep Power
    12

    Default

    How can I access an instance outside of the method that creates it
    OK in a method somewhere you declare a variable and initialise it with "new". The important thing to realise is that "new" provides a reference to a newly created object and that reference is assigned to the variable. What you can do at this point is return the reference to whoever calls the method. That way the caller can assign the reference to the new object to whatever variable they like.

    Here's a simple example:

    Java Code:
    public class Test {
        public static void main(String[] args) {
            String test = "Hello World!";
                // (3) the caller - in a completely different scope - can get
                //     the reference to a string buffer that was created elsewhere
            StringBuffer result = makeLower(test);
                // (4) and use it however it likes
            System.out.println("And the created string buffer is ... " + result);
        }
            // (0) We declare this method as "returning a reference to a string buffer"
        private static StringBuffer makeLower(String str) {
                // (1) new StringBuffer(...) will provide a reference to a string buffer
                //     that depends on the string argument
            StringBuffer ret = new StringBuffer(str.toLowerCase());
                // (2) we "return" that reference to the caller
            return ret;
        }
    }
    Your example introduced a couple of complications:

    (1) The newly created reference has to be returned somewhere within the scope of the variable that holds the variable. Eg if you say "Male testperson = new Male();" then you must say "return testperson;" within the same scope, ie the same pair of {}.

    (2) If you are creating one of two different types of thing (ie Male and Female, you are creating them both), then you have to declare the method that creates them as returning some common super type. In this case it might be Person. (providing Male extends Person, and Female extends Person.)
    Last edited by pbrockway2; 03-21-2009 at 05:24 AM. Reason: typos

  3. #3
    mtyoung is offline Senior Member
    Join Date
    Dec 2008
    Location
    Hong Kong
    Posts
    473
    Rep Power
    6

    Default

    method testy1 return Male Object

    create a Male Object in main method and assume the returned object to your Male Object in main method

    if other method take Male object input parameter,
    you can access that Male object in that method

  4. #4
    meringue is offline Member
    Join Date
    Mar 2009
    Posts
    3
    Rep Power
    0

    Default

    Hi, thanks for your help so far.
    I am still stuck, and cannot compile, with "cannot find symbol" errors for testperson.
    My Male and Female classes now extend Person, as suggested, and I am attempting to return testperson, but it does not work.

    Java Code:
    class Testing
    {
    public static void main(String[] args)
    {
        String gender = "Male";
        testy1(gender);
        System.out.println("Designation from main: "+testperson.designat); 
    }
        
        public static Person testy1(String gender)
        {
        if (gender.equals("Male"))
          {
          Male testperson = new Male();
          testperson.setMale("Test Subject Male");
          System.out.println("Designation: "+testperson.designat);
          }
        else if (gender.equals("Female"))
          {
          Female testperson = new Female();
          testperson.setFemale("Test Subject Female");
          System.out.println("Designation: "+testperson.designat);
          }  
          return testperson;
        }
    
    }
    Something I have noticed:
    If I remove the IF ELSE parts, and assume for simplicity that I only need one gender, the program will compile - but only if I do not attempt to reference testperson in the main method, which defeats the point on two grounds.

    So, please, how do I get testy to return testperson without sacrificing the IF ELSE, and then how do I reference it in the main method?

    Very stuck; help very much appreciated, thanks.

  5. #5
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,565
    Rep Power
    12

    Default

    First: it's a good idea to post the complete compiler message rather than just "cannot find symbol errors for testperson" as these messages are always very helpful. Additionally it's good form to indicate somehow which line(s) they refer to so that people don't have to count to the line number mentioned in the message.

    Did you understand point I called complication (1) in my previous post? You declare - for example - "Male testperson = mew Male();" in a particular scope. What I mean is you declare it within the {} following the first if. You must return testperson within that same {} scope. Once the closing } is encountered the variable testperson will be unknown to the compiler.

    This means that your testy1() method will have to have two return statements - one for each of the "paths of execution": the "if" and the "else if" blocks.

    Secondly did you understand the code I posted? In particular the line I commented as (3)?

    In your main() method you say "System.out.println("Designation from main: "+testperson.designat);". But look at that method: you have not declared testperson, so of course the compiler will grumble. What you have to do is declare a testperson variable and assign the result of the testy1() method to it.

    Java Code:
    Person testperson = testy1y(gender);
    Notice how testperson is declared as a Person, since that is what the testy1() method returns.

    It's really the same problem three times. As far as the compiler is concerned a variable only exists from the time it is declared until the next matching }.

    Java Code:
    // can't use foo here
    void method() 
    {
        // can't use foo here
        if(condition) 
        {
            int foo = 42;  // <-- foo starts being known about here
            // do stuff with foo
        }  // <-- foo ends being known about here
        // can't use foo here
        if(anotherCondition) 
        {
            int foo = 42;  // <-- this is a *different* foo
            // do stuff with the second foo
        }
    
    }
    I should note that even correcting these things (putting two return statements one for each declaration of testperson in testy1(), and declaring and assigning a variable in main()) there may be a small problem remaining in testy1(), but see how you get on.

  6. #6
    meringue is offline Member
    Join Date
    Mar 2009
    Posts
    3
    Rep Power
    0

    Default

    Thanks for your help and patience; I'd worked my way through some of your newer points myself, and you gave me just what I needed to finish it (mainly by pointing out what it was that I hadn't fully understood!).

    Incidentally, was the other problem in testy1() that you foresaw related to the possible eventuality of gender being neither male nor female? I have allowed for this in my new code - but I still cannot carry out my original intent, which is incredibly frustrating.

    I want to access the variable designat (or indeed any of the attributes or methods) in Male or Female, but (I think) because testy1 returns a Person, it will not let me do so inside the main method. This is very depressing; I'll post what I have now, but basically it's just what you described, and so it's starting to look like I'm not even trying myself. My much beleaguered and equally confused housemate, neglected girlfriend, and empty stomach would disagree, but I understand if you decline to assist me further - I'm grateful for your help so far.

    Java Code:
    class Testing
    {
    public static void main(String[] args)
    {
        String gender = "Male";
        Person testperson = testy1(gender);
        System.out.println("Designation in main: "+testperson.designat); //**
    }
        
        public static Person testy1(String gender)
        {
        if (gender.equals("Male"))
          {
          Male testperson = new Male();
          testperson.setMale("Test Subject Male");
          System.out.println("Designation: "+testperson.designat);
          return testperson;
          }
        else //if (gender.equals("Female"))
          {
          Female testperson = new Female();
          testperson.setFemale("Test Subject Female");
          System.out.println("Designation: "+testperson.designat);
          return testperson;
          }
        }
    }
    The error is:

    Testing.java:7: cannot find symbol
    symbol : variable designat
    location: class Person
    System.out.println("Designation in main: "+testperson.designat);

    I assume this is because designat is within Male and Female because if I insert 'String designat;' into Person the System.out.println statement at line 7 works, returning designat as null.

    In case the problem lies in my other classes, Ill post them too:
    Java Code:
    class Female extends Person
    {
      String designat;
    
      public Female()
      {
        designat = "";
      }
    
      public void setFemale(String designation)
      {
        designat = designation;
      }
    
      public void getFemale()
      {
        System.out.println("designat = "+designat);
      }
    }
    Java Code:
    class Male extends Person
    {
      String designat;
    
      public Male()
      {
        designat = "";
      }
    
      public void setMale(String designation)
      {
        designat = designation;
      }
    
      public void getMale()
      {
        System.out.println("designat = "+designat);
      }
    }
    and person is unnervingly empty:
    Java Code:
    class Person
    {}
    Maybe I'm going about this all wrong and my program structure needs to be wildly different to accomplish this (and believe me, I've tried other structures but they seem to become, um, baroque, very rapidly, and fail to achieve anything) but it seems to me that it can't be that hard or I would have found it in tutorials or discussion from other similarly frustrated people elsewhere over the course of my many hours scouring the web??? I just want to access instances of Male and Female outside of the method that creates them -what piece of basic knowledge (or the implementation of said) is wildly eluding me here?

  7. #7
    pbrockway2 is offline Moderator
    Join Date
    Feb 2009
    Location
    New Zealand
    Posts
    4,565
    Rep Power
    12

    Default

    Incidentally, was the other problem in testy1() that you foresaw related to the possible eventuality of gender being neither male nor female?
    Yes, exactly.

    Testing.java:7: cannot find symbol
    symbol : variable designat
    location: class Person
    System.out.println("Designation in main: "+testperson.designat);

    I assume this is because designat is within Male and Female because if I insert 'String designat;' into Person the System.out.println statement at line 7 works, returning designat as null.
    You seem to understand this problem correctly.

    Stand back from it a moment and consider what testy1() actually does. It creates a person based on the desired gender. This sort of method is often called a "factory" method and it is clear that it must be declared to return a Person (rather than anything more specific) because it won't know until runtime which gender is wanted. (and may be called repeatedly to create Person instances of different genders.)

    Java Code:
    public static void main(String[] args)
    {
        String gender = "Male";
        Person testperson = testy1(gender);
        // Stop here and think
        System.out.println("Designation in main: "+testperson.designat); //**
    }
    So you are committed to testy1() being declared to return a nospecific Person. (I'll just say testy1() must return a Person). So in main(), you know you are going to get a Male but the compiler does not. That's the thing about factory methods: you know you will get an instance of some general type, but you don't know the specific type you're going to get.

    Consider what would happen if instead of "hardcoding" then gender you said

    Java Code:
    String gender = args[0];
    ie got the gender from the command line.

    The point is that at the point marked "Stop/think" you cannot rely on testperson being anything more specific than a person. The compiler will insist on this.

    Luckily in this case there's no problem. Both Male and Female have a designat instance variable. You have seen that if you have such a variable in the Person class the problem goes away. So do that: take the designat stuff out of Male and Female and put it into Person.

    This makes perfect logical sense: it is as a person that someone gets a designation, ot as a male or as a female.

    Notice that, eg, a Male IS-A Person. (Sometimes IS-A is taken as some sort of "marker" of being a subclass - I just mean it in its plain English sense: a male is a person.) So designat and other stuff within the Person class will be available for use within the Male class.

    Now your code will look something like:

    Java Code:
    class Person 
    {
      String designat;
    }
    
    class Male exteds Person
    {
        // don't need this because a male will
        // have their designation *as a person*
      //String designat; 
    
      public Male()
      {
        designat = "";
      }
    
      public void setMale(String designation)
      {
        designat = designation;
      }
    
      public void getMale()
      {
        System.out.println("designat = "+designat);
      }
    }
    (Tiny change really. Female is similar.)

    The getMale()/setMale() methods are a bit of a mystery to me. setMale() looks like it should be called setDesignation() since that is what it does. In that case it would do exactly the same thing in the Male and Female subclasses and, hence, would be another candidate for puttig into the Person superclass. Likewise getMale() which would be better called printDesignation().

    (In fact you haven't actually said what the Male/Female classes are supposed to do. SO it's hard to know if you are "going about it all wrong".)
    Last edited by pbrockway2; 03-22-2009 at 01:43 AM. Reason: just replaced the keyboard - and the new one's 'n' is playing up ;-(

Similar Threads

  1. accessing instance variables from static methods
    By ravian in forum New To Java
    Replies: 7
    Last Post: 03-01-2009, 10:09 PM
  2. [SOLVED] Non-synchronized instance method of an Object
    By piyu.sha in forum Threads and Synchronization
    Replies: 2
    Last Post: 10-06-2008, 06:35 AM
  3. public instance method
    By steve123 in forum New To Java
    Replies: 5
    Last Post: 06-20-2008, 08:45 PM
  4. Instantiation using an instance factory method
    By Java Tip in forum Java Tip
    Replies: 0
    Last Post: 03-29-2008, 12:35 PM
  5. Instantiation using an instance factory method
    By JavaBean in forum Java Tip
    Replies: 0
    Last Post: 09-26-2007, 08:25 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •