1

Noob java question.

For my project, I have a class model defined in XML file, which I then transform into a model. For example:

<model>
    <class name="abc"><field>one</field><field>two</field></class>
    <class name="xyz"><field>f1</field><field>f2/field></class>
</model>

and this gets transformed into:

public class abc {
    String _one;
    String _two;
    public String get_one() {
        return _one;
    }
... and so on you get an idea

Obviously, it would be a nuisance to transform each class into its own .java file. It would be much more manageable to pile them up in a single .java file. However, java has this requitement that each class must be defined in its own file, and the file name must match class name. Otherwise, compiler will show error: The public type XYZ must be defined in its own file

It's likely possible to define it like this:

public class ModelContainer {

    public class abc {
        ...
    }
    public class xyz {
        ...
    }
}

Is there another way? Ideally, I'm looking for a compiler switch or something of that kind, which would disable the requirement to have each class in its own file. I am using Eclipse if that makes any difference

galets
  • 17,802
  • 19
  • 72
  • 101

4 Answers4

1

If you're ok with using inner classes then yes, this will work but you'll have to obtain an instance of the outer class each time you want to instantiate an inner class:

public class ModelContainer {
    public class abc {
        ...
    }
    public class xyz {
        ...
    }
}

Also you can declare the nested classes as static, so it won't be necessary to instantiate the outer class first:

public class ModelContainer {
    public static class abc {
        ...
    }
    public static class xyz {
        ...
    }
}

Take a look at this post for additional details.

Community
  • 1
  • 1
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • Coming from .NET background, it was my assumption, that if you declare class as static, you will not be able to create an instance of it. This is not how it works in Java, is it? – galets Nov 01 '13 at 16:48
  • @galets in Java things work different, see this [post](http://stackoverflow.com/a/12836558/201359), but long story short: yes, you can instantiate static nested classes in Java. – Óscar López Nov 01 '13 at 16:49
  • @galets Yes, `static` means something entirely different in Java (as does `final`), so don't assume that modifiers transfer until you read the Java rules for them. – chrylis -cautiouslyoptimistic- Nov 01 '13 at 16:53
1

Interestingly enough, it's not actually a language requirement to have each top-level class in its own .java file:

If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:

  • The type is referred to by code in other compilation units of the package in which the type is declared.
  • The type is declared public (and therefore is potentially accessible from code in other packages).

That said, since the compiler may enforce such a requirement, all portable code should conform to the practice.

Regarding your specific case, you should consider the one-top-level-class-per-file rule to be a language requirement. The usual approach is in fact to generate a separate .java file for each class (there are a number of annoying aspects to using nested classes, even static ones), but you could work around this by using nested classes if you have a better reason than not closing and opening files.

Community
  • 1
  • 1
chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • That is indeed interesting. As I suspected, there is no reason other than a convention to disallow this. That made me think there should be some sort of a switch to disable that check. – galets Nov 01 '13 at 16:59
  • @galets The entire language is "convention". Convention serves a useful and important purpose and shouldn't be disregarded for minor reasons. – chrylis -cautiouslyoptimistic- Nov 01 '13 at 19:35
  • don't get me wrong, you seem to be a language purist, and more power to you, I'm not here to desecrate anything. But personally I write software for living, so to me language is a tool. Tools are there to make my life easier, not another way, so I have no reservations against bending it the way that suits my needs – galets Nov 01 '13 at 20:28
  • @galets I'm hardly a "purist", but putting classes in their own files is even more basic than starting class names with a capital letter. If there's a good reason to lump them all together, then sure, but otherwise, your API is going to be confusing to anyone trying to use it. – chrylis -cautiouslyoptimistic- Nov 01 '13 at 20:35
  • well... are you finding the reason I brought up to be not good enough? – galets Nov 01 '13 at 21:03
1

An alternate, but slightly more-sophisticated approach would be to skip creating Java source at all. You could use a bytecode library such as Javassist or ASM to create class files directly. Essentially, you would be compiling your XML declaration to executable code.

If you are creating simple value objects as shown, this would be pretty easy.

You seem to have a problem with generating large numbers of files, so you could write the class files directly into a JAR file (using the ZIP I/O classes) and generate your synthetic classes as a single library file.

(You might wish to mark these classes as synthetic, although the XML declaration could be considered source code, meaning that they are not technically synthetic.)

Charles Forsythe
  • 1,831
  • 11
  • 12
0

The compiler switch you want doesn't exist. Ensuring that each class is in a correctly-named file - and in the correct place in the directory hierarchy, assuming you're organizing your classes in packages - is always enforced by the Java compiler. Most Java devs wouldn't dream of turning this off, as this way of organizing one's source code is considered good practice. (Therefore Java devs have minor nightmares when attempting to navigate large, unruly projects in languages like C# that don't enforce this restriction.)

The only classes that don't need to obey this constraint are anonymous or inner classes, but your application shouldn't consist mostly of these.

pobrelkey
  • 5,853
  • 20
  • 29
  • Normally, I wouldn't be breaking normal coding practices for the platform. But as you can clearly see in this very instance it makes sense – galets Nov 01 '13 at 16:57