Results 1 to 8 of 8
  1. #1
    nttaylor is offline Member
    Join Date
    Dec 2009
    Posts
    5
    Rep Power
    0

    Default confused about packages and import

    I am trying to put my main class (and "main" method) in one file and some constants (and eventually methods) into a separate file.

    Also, I want to be able to access the constants without qualifying the namespace by prefixing the name of the external file / class. Is there any was to make this work?

    If file 1 (Testy.java) is:

    public class Testy {
    public static void main(String args[]) {
    System.out.println(SOME_CONSTANT);
    }
    }

    and file 2 (Westy.java, which defines SOME_CONSTANT) is:

    public class Westy {
    public static final String SOME_CONSTANT = "hello";
    }

    how can I get it to compile?

    I know I could write "System.out.println(Westy.SOME_CONSTANT)", but again, I would like to be able to use these constants without a qualifier.

    Both files are in a directory called "testy", and I've tried putting "package testy;" at the top of both files, but that didn't work. Putting "import Westy.*;" into "Testy.java" caused a different error (which also surprised me, since I thought that CLASSPATH was supposed to include the current directory automatically).

    Is what I'm trying to do possible? And why didn't that import statement work?

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

    Default

    The classpath is whatever you set it to be. (Under some circumstances this can be the current working directory, but you are far better off setting it explicitly when you run the java or javac executables: they both take a -cp argument for this purpose.)

    You can import static members from another class. Put both Testy and Westy in a package and in pack/Testy.java use:

    Java Code:
    package pack;
    import static pack.Westy.*;
    
    // later
    System.out.println(SOME_CONSTANT);
    This practice can lead to ugly code. (name conflicts, "where did that variable spring from?"s)

  3. #3
    nttaylor is offline Member
    Join Date
    Dec 2009
    Posts
    5
    Rep Power
    0

    Default static import from same directory?

    Thank you for your response, pbrockway2.

    After lots of experimenting I finally figured out that if you have two files with the first line "package foo;" and they are both in a directory named "foo", then you have to be in the directory ABOVE foo when you run the compiler and when you run the executable.

    The thing I'm writing isn't very complex and doesn't need a lot of separate files. I don't think I need an explicitly named package. Is there any way to statically import constants defined in another file/class (in the same directory) without naming a package?

    If I remove the package declarations from "Testy.java" and "Westy.java", but try to leave "import Westy.*;" in Testy.java, I get a compiler error.

    But you see what I'm trying to do - access the constants defined in Westy.java without a qualifier. Is this possible?

    Many thanks in advance.

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

    Default

    After lots of experimenting I finally figured out that if you have two files with the first line "package foo;" and they are both in a directory named "foo", then you have to be in the directory ABOVE foo when you run the compiler and when you run the executable.

    Yes, exactly.

    In this case the class (or classes) involved would be foo.MyClass, foo.OtherClass etc. The java tools (java, javac etc) will look for the associated files as foo/MyClass.class on the classpath somewhere. We might speak loosely of "MyClass" but we really mean "foo.MyClass". Packages are not exceptional or something that can be ignored or worked around: they are the norm and represent a sane way of organising classes to allow the access privileges we want and avoid name clashes.

    The thing I'm writing isn't very complex and doesn't need a lot of separate files. I don't think I need an explicitly named package.

    To belabour the point: packages are the norm. However simple the thing being written is or is thought to be.

    don't think I need an explicitly named package. Is there any way to statically import constants defined in another file/class (in the same directory) without naming a package?

    If I remove the package declarations from "Testy.java" and "Westy.java", but try to leave "import Westy.*;" in Testy.java, I get a compiler error.

    I'm wondering if the compiler error you mention might not be the answer to the question you ask... But decided to look it up.

    You say the classes are in the same directory. Using the careful distinction introduced above of class vs file, this really means that the associated .class files files are in the same directory. So the classes are either in the same package (where referencing the static members you have already seen) or they are both in the default (unnamed) package.

    Now as far as importing an accessible static member from a named type when that type is in the unnamed package goes: you can't do it.

    If you're interested in the details have a look at this bug report. The "party line" is simple: "classes from the unnamed namespace are not in scope in an import declaration. I believe the compiler is behaving as specified."

    Those commenting on this hold a variety of views. And they cite chapter 7 of the Java Language Specification which you can read for yourself.

    fwiw, I would place myself among those who think think the restriction is no big deal but that the JLS could have been more explicit in 7.5.3 and 7.5.4 in declaring the fact that static imports from the unnamed package are not possible.

  5. #5
    nttaylor is offline Member
    Join Date
    Dec 2009
    Posts
    5
    Rep Power
    0

    Default

    Thank you pbrockway2 for that very thoughtful explanation.

    I think the closest I can get to the behavior I want is a main class (e.g., "Testy") that resides outside a directory named (for example) "pack".

    Inside "pack" would be "Westy.java" (with its own class declarations), and "Constants.java" (with some constants). The first line of both files would be "package pack".

    Then in "Testy.java" I can put "import static pack.Constants.*" for unqualified access to the constants, and also a regular (non-static) "import pack.*" for unqualified access to classes defined in "Westy.java".

    So in this way I get my unqualified class names and constants, although I have to have at least one file ("Testy.java") residing *outside* the directory where everything else resides.

    Does that sound right? Ideally I still think I would like to have everything in one directory, but I suppose that's not the Java way.

    Thank you again for your help. It's rare to find such clearly written and well considered answers to queries.

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

    Default

    All three files can be in the same directory (classes in the same package). It's just that you can't do any importing if that package is the unnamed one.

    In your other thread you said you tried all sorts of things but they didn't work. But without knowing what you tried and what happened when you tried that, it's difficult to comment. It is quite possible you weren't specifying the classpath correctly.

    Here is how to have the three classes in the same (unnamed) package. Because they are in the unnamed package the constant can't be imported and, so, must be specified using its fully qualified name:

    Java Code:
    pbrockway@lind6off:~/Temp$ ls
    Constants.java  Testy.java  Westy.java
    pbrockway@lind6off:~/Temp$ cat Constants.java
    public class Constants {
        public static int ans = 42;
    }
    pbrockway@lind6off:~/Temp$ cat Testy.java
    public class Testy {
        public static void main(String[] args) {
            Westy test = new Westy();
            System.out.println("The answer is " + Constants.ans);
        }
    }
    pbrockway@lind6off:~/Temp$ cat Westy.java
    public class Westy {}
    pbrockway@lind6off:~/Temp$ javac -cp . *.java
    pbrockway@lind6off:~/Temp$ java -cp . Testy
    The answer is 42
    pbrockway@lind6off:~/Temp$

    And here is how the classes would look if they were all in a named package. Now everything can be referred to using its unqualified name.

    Java Code:
    pbrockway@lind6off:~/Temp$ ls pack            
    Constants.java  Testy.java  Westy.java        
    pbrockway@lind6off:~/Temp$ cat pack/Constants.java 
    package pack;                                      
    public class Constants {                           
        public static int ans = 42;                    
    }                                                  
    pbrockway@lind6off:~/Temp$ cat pack/Testy.java     
    package pack;                                      
    
    import static pack.Constants.*;
    
    public class Testy {
        public static void main(String[] args) {
            Westy test = new Westy();
            System.out.println("The answer is " + ans);
        }
    }
    pbrockway@lind6off:~/Temp$ cat pack/Westy.java
    package pack;
    public class Westy {}
    pbrockway@lind6off:~/Temp$ javac -cp . pack/*.java
    pbrockway@lind6off:~/Temp$ java -cp . pack.Testy
    The answer is 42
    pbrockway@lind6off:~/Temp$

    (If you're used to Windows commands "ls" is like "dir" and "cat" is like "type".)

    Note there is a single (static) import in the second case and none at all in the first. Ie you don't import classes from the same package (named or not).

  7. #7
    nttaylor is offline Member
    Join Date
    Dec 2009
    Posts
    5
    Rep Power
    0

    Default

    Amazing! I did try this before, but I hadn't figured out yet that it matters what directory you're in when you invoke javac. I was trying to compile Testy.java from within its own directory.

    I guess that pretty much closes the book on this one. Thanks again pbrockway2! I wish I could buy you a beer!

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

Similar Threads

  1. import packages
    By gregorio99 in forum New To Java
    Replies: 3
    Last Post: 11-06-2009, 01:43 PM
  2. Very confused Plz help!!
    By ratb0y in forum NetBeans
    Replies: 0
    Last Post: 02-14-2009, 05:34 PM
  3. Confused
    By coldfire in forum New To Java
    Replies: 3
    Last Post: 01-13-2009, 02:00 PM
  4. Replies: 3
    Last Post: 02-12-2008, 12:03 PM
  5. Problems with packages (import statements)
    By ai_2007 in forum Advanced Java
    Replies: 1
    Last Post: 06-29-2007, 12:57 PM

Tags for this Thread

Posting Permissions

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