jQuery in Action, 3rd edition
The moose likes Java in General and the fly likes Inner Classes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login

Win a copy of Head First Android this week in the Android forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Inner Classes" Watch "Inner Classes" New topic

Inner Classes

Jay Gehlot

Joined: Feb 05, 2011
Posts: 3

I am learning about Inner Classes and have encountered a compilation error that I am having trouble figuring out.

I have created a class called Invoice (which is the outer, enclosing class) and within this, I have added an inner class called InvoiceItem:

I have created another class called UseInvoice, which creates two objects. One object is an instance of the Invoice class and the other is an instance of the InvoiceItem class.

The Invoice class compiles without any problem, however when trying to compile the UseInvoice class, I get the following error:

C:\Documents and Settings\JGehlot\Desktop\Java Videos\Java Files\Inner_Classes>javac UseInvoice.java
UseInvoice.java:3: package Invoice does not exist
import Invoice.*;
UseInvoice.java:16: cannot find symbol
symbol : class InvoiceItem
location: class UseInvoice
InvoiceItem myInvItem = myInvoice.new InvoiceItem(1,345, "Toy Train", 2) ;
2 errors

C:\Documents and Settings\JGehlot\Desktop\Java Videos\Java Files\Inner_Classes>

Note: UseInvoice.class and Invoice.class and Invoice$InvoiceItem.class are in the same folder (C:\Documents and Settings\JGehlot\Desktop\Java Videos\Java Files\Inner_Classes).

Could someone tell me what I am doing wrong? I think its something to do with the use of the import Invoice.*; statement at the top of the UseInvoice file.


Tom Reilly

Joined: Jun 01, 2010
Posts: 618
Import is used for packages. Invoice is a class. You can use static import as a shortut to get to static members of a class but not inner classes. I updated your code so that it compiles. I also reformatted it and used code tags to make it easier to read. When you use code tags (see UseCodeTags) you will probably get more (better?) responses on this site.
David O'Meara

Joined: Mar 06, 2001
Posts: 13459

welcome to the Ranch
Campbell Ritchie

Joined: Oct 13, 2005
Posts: 43368
You cannot import a class which does not have a package name.
Jay Gehlot

Joined: Feb 05, 2011
Posts: 3
Thankyou Tom for your reply to my first post on this site.

Apologies for not using CodeTags, you are right, it would have made the code a lot easier to read and digest.

I've changed the code as you have suggested, in order to instantiate an object for the inner class and this works fine!

Actually the reason I initially did this is because I have been watching CBTNugget videos for the SCJP exam. The videos are actually quite old (created in 2004) for Java 1.4. The videos actually show this (import Invoice.*; code) and the code compiling, which was why I was a little confused as to why this wasn't working on my machine, using Java 1.6.

Maybe this was possible in Java 1.4??

Anyhow thankyou Tom and also thankyou Campbell.
Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479
This particular thing has not changed between 1.4 and 1.6, or, in fact, 1.0. Import is used for packages, which have periods between each package level. You are using an inner class, which can be referred to as Outer.Inner and therefore possibly be confused with packages.

The capital letter on Invoice makes it suspect immediately; the language has no restriction on the use of capital letters in package names, but there is a strong convention of leading capitals used for class names, not package names at any level.

You could have had:

import one.two.three.Invoice;

followed by code; Invoice in this case is a class name, at the end of its package.

Jay Gehlot

Joined: Feb 05, 2011
Posts: 3
So Ralph, I think I understand what you are saying. Invoice is the class and I am incorrectly trying to import the class, which is obviously not permitted.

I have two class files within the folder C:\Documents and Settings\JGehlot\Desktop\Java Videos\Java Files\Inner_Classes

The first class is Invoice and the second class (which holds main, and call Invoice) is UseInvoice.

Would you suggest to have write the following in the UseInvoice class:

import Inner_Classes.Invoice;
import "Documents and Settings\JGehlot\Desktop\Java Videos\Java Files\Inner_Classes";

I haven't yet gone through the chapter on packages, so I am still trying to find my way here.


Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479

A class is what you do import. If your class Invoice is in a package called billing, with billing in a package called business, you could say:

import business.billing.Invoice;

This would enable you to use Invoice in your class without having to write business.billing.Invoice everywhere. The latter is called, incidentally, a "fully-qualified name" for the class, the former a "classname".

With packages, you can tell the compiler to import all the classes in a specific package:

import business.billing.*;

would allow you to use any class within the package business.billing without having to use the fully-qualified name of that class.

As far as I know, there is no way to import an inner class using "*"; you must enter the inner classname qualified with its outer classname any time you need the classname. I *think* you could import InvoiceItem by itself:

import business.billing.Invoice.InvoiceItem;

But I am not sure and haven't tried it. I am fairly sure you cannot import all inner classes of Invoice using the "*".

Now, as to your files: I cannot tell from your description whether Invoice and UseInvoice are in packages or not. The fact that they are in directories does not tell me that they are in classes. The fact that the directory has an underscore and capital letters suggests that it is not a package name; if it is, it does not follow the widely-used convention I mentioned about packages having names in lower case letters.

Look in the source. If they do not have a "package" statement at the top (it's required to be before any other statements), then they aren't in packages, and don't need to be imported at all. Your code can just say something like:

Invoice currentInvoice = new Invoice();

with no import statement and that will fine. Invoice is a fully-qualified name if Invoice is not in any package.

subject: Inner Classes
It's not a secret anymore!