Psychedelic Panorama of Foo

Á¦ À̸§ÀÌ Inigo Montoya ÀÔ´Ï´Ù. ´ç½ÅÀÌ ³» ¾Æ¹öÁö¸¦ Á׿´¾î. Á×À» ÁغñÇØ.

ÀÏ¿äÀÏ, 10¿ù 05, 2008

 

Inner and Outer classes

¾Æ³çÇϼ¼¿ä. During class on Thursday, one of the topics was about inner and outer classes in java. Rick, had a slide and pointed out pros and cons of each. He pointed out the proper applications, so we would know when to use them. I'm taking my time to write a blog on my impressions of inner vs. outer classes in java.

Outer Classes

Let's start with outer. Really, all normal java classes can be considered outer classes. I am specifically speaking in exception to those. That is, I am addressing outer classes that are not normal java classes. My personal rule on outer classes is NEVER under any circumstances use them. Why? Let's have a look...

I put together some example outer class code here:

public class OuterExample { } class OuterClass { @Override public String toString() { return "I'm an outer class"; } }
  • Outer classes are exactly like package level classes which are almost never useful.
  • Having two classes in the same source file is usually bad (unless it's an inner class.) I know. That's about the same as saying, "Outer classes are bad," but what is really intended is that having all your source is generally to be avoided. While trying to keep all your source organized and not in the same file, you split them up by class into different source files. This is why public classes must have their own source file. If it is necessary to keep classes together in one file, we use a jar for this.
  • You will get eaten alive at code reviews for using this. Be fully prepared for the public humiliation.

Outer classes are exactly like package level classes because you cannot use public or private directives on an outer class. Below is what happens when I use public:

leo@sark~/Local/projects/cs335/OuterInner (16:06:54) [29] ant test Buildfile: build.xml compile: [javac] Compiling 1 source file to /home/leo/Local/projects/cs335/OuterInner /target/classes [javac] /home/leo/Local/projects/cs335/OuterInner/src/main/java/OuterExample .java:57: class OuterClass is public, should be declared in a file named OuterCl ass.java [javac] public class OuterClass { [javac] ^ [javac] 1 errors BUILD FAILED /home/leo/Local/projects/cs335/OuterInner/build.xml:42: Compile failed; see the compiler error output for details. Total time: 0 seconds

Below is what I get when I use private:

leo@sark~/Local/projects/cs335/OuterInner (16:06:07) [28] ant test Buildfile: build.xml compile: [javac] Compiling 1 source file to /home/leo/Local/projects/cs335/OuterInner /target/classes [javac] /home/leo/Local/projects/cs335/OuterInner/src/main/java/OuterExample .java:57: modifier private not allowed here [javac] private class OuterClass { [javac] ^ [javac] 1 error BUILD FAILED /home/leo/Local/projects/cs335/OuterInner/build.xml:42: Compile failed; see the compiler error output for details. Total time: 0 seconds

IMHO, it is better to put all your classes in separate files for organization purposes and also for maintenance. It's a real pain to have to search for what file a class is defined in if it isn't one by name. Further, the actual "classes" themselves are in separate files by name. For example, notice in the following that OuterClass gets its own file; therefore, why even bother putting your outer class in another file if it's just going to obfuscate things?

leo@sark~/Local/projects/cs335/OuterInner (16:35:56) [30] ls target/classes/ InnerExample.class OuterClass.class InnerExample$InnerClass.class OuterExample.class

Inner Classes

Inner classes are extremely useful, but I think they are especially useful when you need a private or protectedclass. Unlike, outer classes, you can make your inner class private or protected. This is useful if you need descendants only or if you want no other classes to know about a specific class while you also need to generalize or abstract some functionality within a class. This is an example:

public class InnerExample { private class InnerClass { @Override public String toString() { return "I'm an outer class"; } } }

public

public is used when you want other classes to have access to this class completely unrestricted. Why would you do this? I'm not sure yet, but have a look at java.util.Map.Entry. It does just that.

protected

protected is useful when you want only the containing class and descendants of the containing class to have access to it. Usually, you want to share implementations with descendants while generalizing or abstracting that implementation. protected inner classes are perfect for this. Probably the most used.

private

private is my favorite because you can generalize or abstract your implementation while preserving inheritance. IMHO, descendants should not be coupled to the implementation of their ancestors, so I am really conservative on the use of protected. This makes my favorite choice private.

static

static is not particularly useful with inner classes. You can use static, but it is the equivalent of adding abstract to method declarations in an interface. It's slightly redundant because classes are already static. Saying the class is static is like saying the class is a class.

Output

leo@sark~/Local/projects/cs335/OuterInner (16:35:56) [30] ls target/classes/ InnerExample.class OuterClass.class InnerExample$InnerClass.class OuterExample.class

Now compare the class outputs of inner vs. outer classes. As mentioned before OuterClass gets its own file, but InnerClass is shown as InnerExample$InnerClass.class. This emphasizes the inner-ness. It shows which class the inner class is contained within. This only further stresses the difficulty of finding which source file to find the outer class in if nothing distinguishes it as an outer class. Anonymous classes are similar. An anonymous class would be called, InnerExample$1.class or InnerExample$2.class. The reason is because anonymous classes don't have a name, so java just gives them a number.

·¹À̺í: , ,





This page is powered by Blogger. Isn't yours?

¿¡ °¡ÀÔ °Ô½Ã¹° [Atom]