That public static class feature makes it so you can declare a class inside another class that has external visibility.
Huh? "static" doesn't give an inner class external visibility. "public" does. I don't understand this page. Please explain.
You are correct. You don't understand. http://www.javaworld.com/javaworld/javaqa/1999-08/01-qa-static2.html.
That doesn't show static granting external visibility, it shows public granting external visibility. See http://www.javaworld.com/javaworld/javaqa/2000-10/01-qa-1006-inner.html, specifically:
"Because static member classes operate just like any other members in a class, they follow the same access control rules and can have private, package, protected, or public access."
Static doesn't "make it so you can declare a class inside another class that has external visibility." Public does.
No, a static class is a class that has global scope. Effectively, declaring a class static means it is an "outer" class that can be instantiated by itself.
But that doesn't determine it's visibility. It means it doesn't need or have a reference to an instance of the enclosing class.
The static inner class may be defined with the private or protected attribute so that there is a little more control over their visibility than for outer classes (which can be declared with package or public access only). A static inner class may have access to private static members of the enclosing class. Actually, I don't ever see a reference to a private static inner class.
They are allowed. They are not visible outside the enclosing class. Static has no effect on visibility. You can make any member class public, not just static member classes.
[The static modifier on a nested class does not make it globally visible. See for example: http://java.sun.com/docs/books/tutorial/java/javaOO/QandE/nested-answers.html Another excellent discussion of the use of static vs. non-static member classes is in Chapter 4 of JoshuaBloch's excellent book, EffectiveJava. Page 91, Item 18, Favor static member classes over nonstatic.]
This has several problems:
Yep, this is an advantage. You could use package level instead of private though. Then you break modularity and encapsulation. You break that also when you have a public class (which a static class is [No, a public static class is public. A private static class is private.]) that can access private variables. No difference. Very big difference: a static inner class is enclosed in the larger unit which is the class itself, so there's no break in modularity, it's basic inner scope has access to outer scope. Boy, you never did program in Pascal or what?
That's a weird kind of modularity.
class SingletonExample? { private SingletonExample?() {} private static class Instantiator { static SingletonExample? instance = new SingletonExample?(); } public SingletonExample? instance() { // the private constructor of SingletonExample? is called exactly once // and exactly at this point as an effect of loading the Instantiator class return Instantiator.instance; } }
The other class extensions, like anonymous classes, are fine, but this one was unnecessary and is a mess. Or is it?
The static keyword does not determine the visibility of inner classes. If an inner class is not declared static, then every instance of the containing class has a copy of the class declaration including any class variables and method definitions. A static inner class declaration is shared by all instances. This difference may be important for some code. Also, having a class definition for every instance may introduce certain resource use issues.
Oh, but I like this mess, and I use it most of the times. It's way cool. Few files, few things to worry about. Let's remember the glorious days of Pascal and C when you'd write a whole project in a handful of files or in just one file. A lot of unix utilities including the complex ones, are in just one file.
One example is a concrete factory that may need access to private constructors and have more intimate knowledge of the object they create. Of course, factories are not instance relate,so the best solution is to put them as static inner classes inside the classes they will create.
It's even better, inside the factory method you can derive from the class you create and override methods, as anonymous inner classes, why pollute the namespace with the names of derived classes? If somebody wants to know something about a particular mechanism that I expose through a factory and an interface, the whole thing can be in just one file. It's just about circumventing limitations that are imposed by JavaLanguage with regards to code modularity and code layout, and twisting the language in unexpected way, to suit your chosen quality attributes.
Jumping from file to file can be a very unpleasant experience.
Jumping from file to file can be a very unpleasant experience.
We have packages and they work fine. Trying to make sense of a class with tons of other classes in it is impossible.
No, packages don't solve these problems. The mere fact that I have to move my eyes from one window to another and follow related things (maybe in the context of the same use case), in different visual spaces is very unpleasant. Your resolution about a class with tons of other classes is untenable. It's not tons, it is a handful, maybe one or two. And they are very simple, so simple and so related in the functionality, that moving them inside their own file/window/visual space is unjustified and wasteful.
So you put your entire program in one method one class? Or you have to scroll and look down or up to find the other classes. Or maybe you should try solid interfaces so you don't have to look at them so often?
Do we smell a StrawMan? Well, I don't put my entire program in a file, but that ain't bad either. If you browse some Unix sources, you'll see lots of "program in one file" cases. You seem to hold the unjustified belief that polluting your project with lots of little files makes it somehow a virtue. Well, it ain't so, buddy.
So, you assume that I don't write interfaces, hmm, that's nice. Let me see you, buddy. Here's an example on wiki that I posted some time ago, with quite a few inner classes (some of them static, some classes, are used just for the sake of a namespace) - I didn't know at the time that people judge these things so harshly. So would you take the DiningPhilosophersChallenge please? Put your code where your mouth is, and let me see if you can restructure the code so that it looks more pleasing in a standard IDE.
How about the scrollbar ? Well, it so happen that I choose to put inner classes, exactly where they mater or very close to that point, so I don't have to use the scrollbar, as a matter of fact, even in that case, you can always use the little tree-structured outline to navigate to different portions of the same file, while jumping through packages is entirely wasteful.
Well, buddy, if you have interfaces why do you feel the need to look at them so often it impacts your class structure?
Well, buddy, I look not only at interfaces, but also at implementations, and no matter how often or how seldom I look at them, jumping through hoops to get the drill, that ain't nice.
Well buddy, buddy, implement it, test it, then let it be. It would be odd to keep needing to see implementations so often that you let it impact your class structure. It's also a little odd to prefer scrolling rather than just selecting a class from class tree on the left hand side of your IDE.
Well, buddy, buddy it happens so often that I sometimes need to revise the implementation, or to revise interfaces. I very seldom need to change class structure, thank you very much. But you have a totally gratuitous problem with the way I see fit to organize code elegantly and efficiently, and you claim that this is some kind of AntiPattern. This is nonsensical, and has to be sorted out; the claim cannot stand - either you are right and I am wrong, which means this is really an anti-pattern, or I am right and you are wrong, meaning this is a very solid and legitimate way to organize some parts of code, and while you may prefer other ways and even be irritated by my evil ways, it is most definitely not an anti-pattern.
I brought logical arguments to the table, and even an example, that so happened was already available. You brought a StrawMan and lots of hand waving, so where do we go from here ?
Where all such discussions go, no where. I advocate putting static classes in the package because it is cleaner and clearer both for the static class and the class containing it. Access is trivial because it is a button click in your IDE.
Then if you only advocate, you shouldn't have the audacity to classify this as an AntiPattern as the title suggests and put it on the list of JavaDesignFlaws. This is not a language flaw, it is a useful and carefully designed feature. If you don't like it, don't use it.
There's nothing cleaner, nor clearer in putting lots of classes at the package level. It's often times, extremely muddy. Some of them reside better within the "namespace" of the class. Actually that's maybe not a design mistake, but certainly a limitation that namespaces are limited to directory. Let's see, you want to make a minor modification to this nice open source software, and when you opened the package, there's 40 classes in one package. Where do you begin? Quite likely, nowhere, it is a nightmare finding the right place. If more care is exercised in arranging classes together in one file, and under the class namespace, as in Java static classes, you'd see that you can arrange the code so that when somebody opens a package, only a handful of classes will show in the browser, and those are the classes that really matters. All the other classes are typically subservient to the main concepts, or are implementation details, that are not important when a first-time developer opens up a package view. The package code view should show the essentials about the code.
Now one more technicality: packaged classes don't have access to private methods. Static inner classes do.
Large Java files are more of a barrier to readability and maintainability than large numbers of Java files. For that reason, I often ExtractClass, and static inner classes are the easiest to extract. Code with nontrivial inner classes is generally more difficult to deal with, though small inner classes aren't a problem.
If you can't back your opinionated chat with anything remotely verifiable, then I am going to rename this discussion and dismiss it's assertive title. You can't just say something is so. Some people like tons of little files. Others, including me, don't. Tons of little file with tons of little classes are an inadvertent pollution, and taking out classes just to reduce the lines per file smells strongly as dogma. If the class you extract has some business on its own, then fine, otherwise leave it where it is.
If one class is only used in the context of another class, then it should not pollute a larger namespace. That's a basic principle of code modularity, it's there ever since they designed nested procedures in Algol. To contest basic modularity principles with refactoring dogma is irrelevant.
We're both being opinionated; you prefer fewer files, each with multiple classes, while I don't. When I examine source code, it simplifies comprehension when every member variable and every method belongs to the same class. Long source code files make my eyes blur. Namespace pollution is a valid concern, but Java packages minimizes that factor.
Well, I prefer that every module of code should stay in its own unit of abstraction. And since Java does not have modules, but has packages that are less than desirable as a modularity unit, I can organize more code into a file, without having to suffer the idiosyncrasies of Java. You still have to learn one of the best SoftwareEngineering principles around: Do not write code in a programming language, write code into a programming language (from DavidGries ScienceOfProgramming?). What it says is that you should design your code as you'd have the best means of abstraction and programming language features around, and after that, translate your design into the programming language that you have at hand.
It's rather superficial whether to include multiple classes in a single file; the code will be equally modular either way. Consequently, I'd recommend separate files per class, to improve readability and maintainability.
You actually decrease readability and maintainability by following the rule that all classes should be in a separate file. The simple reason is that you pollute the namespace with too many names, therefore making it harder to comprehend, and also by isolating code that doesn't make sense on its own, out of its natural context, you make a more exhausting effort to read.
A good rule is that all dependent classes should be inner classes or static inner classes (for the lack of better Java solution to modularity problems). For example: java.util.Map/java.util.Map.Entry java.util.WeakHashmap?/java.util.WeakHashmap?.(Entry,EntryIterator?,EntrySet?,HashIterator? ...).
Names are like roads. They tell you where you are and where you can go. You can only pollute a namespace of the classes don't belong in the package. If you find they don't then start a new package so the names make sense in that context. Nothing is harder to read or maintain than huge files with tons of classes in them.
Well, I can create and maintain those files no problem. Starting a new package is not a good solution. So you've got a problem that other people don't. It's your problem, not a problem with Java static inner classes.
You may not, but anyone coming after you will be lost. Why is starting a new package not a good solution? That's what they are for. They are not scarce resources that should only be used as a last resort.
I don't have a problem; the engineers that contributed to the Java SDK also seem to prefer inner classes as a way of better organizing dependent classes, so I would say it's a good trend. It may be that your unwillingness to accommodate or psychological repulsion towards big files is more of a factor than any other objective factor? Get used to it, or hypothetically I'll recommend against hiring you on my project, and usually I am the guy that they trust on technical interviews. Other people around me and got used to it no problem and are happy.
What would you do in the case of java.util.WeakHashMap? ? Would you create a package java.util.weakhashmap and put the inner classes in there?
Creating a new package for all major classes that need auxiliary classes is bad, because it further pollutes the namespace; it is also bad because it breaks existing package-level collaboration when you move the main class in another package. Also subpackages are just subdirectories with no semantical meaning attached to the relationship. So it is just bad modularity that you get from creating tons of packages because of your unjustified dislike of inner classes.
Then if you only advocate you shouldn't have the audacity to classify this as an AntiPattern as the title suggests and put it on the list of JavaDesignFlaws. This is not a language flaw, it is a useful and carefully designed feature. If you don't like it, then don't use it.
I didn't say it was AntiPattern, i just said it was JavaDesignFlaws. Which doesn't seem very audacious. It just seems like someone who has been working with code that uses this "feature" and can find nothing careful or clarifying about it.
You should try programming in more advanced languages like StandardMl?. That should give you an idea what modules really mean. It is not about packages.
Few files, few things to worry about.
And if I were interviewing you, you would be dismissed. That you carve up your world by files instead of packages is your idiosyncratic methodology that you ignorantly use to judge everyone else. Pointing to java.util as a package architecture to emulate is amazing. Look at the word util. It means nothing. It's a garbage dump.
What a strange page. Costin is right, I don't see any actual arguments here supporting use of packages instead of static inner classes. The pro-package side of it seems to be more about personal preferences and prejudices with no supporting arguments. -- DougMerritt
And the reverse is true also. I am not sure what kind of killer argument you can expect here. If you are fine with huge complicated files then that is personal preference. Not one i share having had to maintain and extend such code, but it is still a preference.
Hey, first of all, there's the technical argument that packages do not satisfy all modularity requirements. This has been stated several times, and you didn't address. Second you create a StrawMan about "huge complicated files". It depends what you think of as complicated. If you are going to whine about 1000 lines of code here and there, then maybe you shouldn't be working on maintaining software after all. GrandMasterProgrammers created file sources with thousands of lines of code.
But the more fundamental problem is that you are the (anonymous) guy making the strong claim here, therefore the burden of proof is on you. You declared that JavaStaticClassesIsaTotalMess, you added it to JavaDesignFlaws, but you have nothing to substantiate but the personal preferences of an anonymous wiki lurker, and you say that not having solid arguments for the strong claims you make is OK. It is not OK, it is profoundly wrong and detrimental to wiki. Just think about it. -- CostinCozianu
I've got to agree with Costin here, nothing you've said seems to make any sense at all. You don't even seem to realize that static and public are different things. There's nothing wrong with inner classes, they are very useful for making dependent classes and keeping the namespace clean.
Yah, stupid me. Guess it's impossible just to disagree anymore. One persons clean name space is a dirty file.
It's never been considered good form to disagree without giving reasons. The total extent of your arguments consists of adjectives like "clean" and "dirty" and "messy". Give it up.
I do have reasons, given several times, based on numerous instances of maintaining and extending these files that have many classes embedded in them. They are nearly impossible to figure out. For exactly the same reasons that long functions are hard to understand. I don't think i used the word dirty, but clean is oft used word in computer science. I find one class to a file, other than very simple inner classes, much cleaner and easier to understand. You don't. Give up thinking your views are the only possible take.
You can "disagree" on better terms, or to put it otherwise, understatements are always encouraged on this wiki, unless you have some very strong backing arguments like GoToConsideredHarmful? or something comparable. But claiming that coding practices followed justifiably by reasonable engineers are anti-patterns or "design flaws", because of somebody's personal preferences is not very helpful.
Your "findings" may be influenced by something very personal, like being used to SmallTalk that has a different cultural background. Other people have absolutely no problem with files in the hundreds of LOC (that's mostly what we are talking about here) and even in the thousands of LOC where warranted. Smalltalk programmers are typically used to see 5-15 LOC at a time in the code browser, but that doesn't say that 5-15 is the golden rule.
We could rename this page as StaticClassesControversy?, cut out the chaff, summarize the pros and cons, and remove it from JavaDesignFlaws, what do you think? -- Costin
Sounds like a plan. In response to the other guy:
Ha! As it happens, I don't program in Java, so we're not talking about my opinion. I'm commenting on the arguments on this page. Costin has presented reasons. You have presented unsupported prejudices. As a non-Java programmer (I do know the language, mind you, so it's not like I don't understand what y'all are talking about, I just don't code in it), I'm relatively neutral.
Your comparison to long functions is finally a small argument on your side of things; did I just overlook something like that above?
But here I'll bring in my opinion: I've tried putting every class/function in its own file in multiple languages, and the tradeoff turns out to be that each small file is a bit easier to read, but then you have to deal with being lost in a huge ocean of files, which is a sharp decrease in cleanliness. This is only true on big projects, of course, so if you're talking about projects where you only end up with, say, a dozen classes/files, then whatever, it doesn't matter much.
There is a tradeoff to some extent between the total number of files versus the length of each; neither number should be maximized.
You did say the word "dirty", btw, right in the paragraph I responded to! -- dm
There's also the matter of really liking to do things with objects. I find inner classes useful so I can make private helper objects that are used only within a specific class. I don't want anyone else to see or use it, so it doesn't need to be out in the package. It might be something really small like parsing a weird string into object form so I can work with it easier. Inner classes allow this. Hell, I'm not even a java programmer, I do C#, but the same issue is relevant. Putting classes inside of classes is damn useful, just like putting functions inside of functions will be when we get anonymous functions next version. Objects should not require separate files. I do put parent objects in their own files, so I understand you're argument. I like one object per file too, but to me that doesn't count for inner classes.
The guy that is pro-inner-classes has a certain point - I have found them useful for some things, particularly in complex gui's, but I have never needed to use static inner classes and he makes some absurd claims about readability and namespace that are pretty much rubbish. If you ever work on a decent sized enterprise project, clarity of design and encapsulation beats the living daylights out of big files with tonnes of classes in them. Try jumping into a 10,000 line session bean with loads of inner classes in it, (most of which should be utility classes kept in a separate package) and then try and understand it. And by a decent sized project, I mean on the order of hundreds of classes. It is far easier to understand a bunch of clearly defined classes than a huge mess of a file. The key concept of object-orientation is encapsulation - which none of the pro-inner-classes guy takes into consideration. And he probably ends up re-implementing the same helper classes every time he starts a new project, or cutting and pasting loads of code around. So obviously his approach is not conducive to re-use, another win that the object-oriented paradigm is supposed to provide. And if he turned up for a job where I work he wouldn't make it to the second interview as he clearly has a lack of understanding of object oriented concepts and worse appears to be an egotistical programmer which is hugely destructive. -- AnonymousDonor
Static inner classes (call them nested classes, that's what the Java Spec defines them as) provide more encapsulation than packages - in some ways. A NestedClass has access to the enclosing scope, but can only accessed from within that class (and its internals can't be mucked with by anyone). A package-level class has no direct access to anything, but can be accessed by any other class in the package. The context required to understand a NestedClass is somewhat larger, but the CostOfChange for a package class can be significantly higher, as it's tougher to track down all references.
I tend to use a mixture of both. Nested classes get used if the class in question really is private to a specific class, or otherwise tightly coupled. FacadePattern is an potential example, as is GUI work, as are PlainOldDataStructure?s, as are things like Map.Entry in the Java standard library. Package level classes are for things that will get re-used, like most utilities. And it's quite common for a class to start out as a NestedClass and then migrate to package-level, but there's nothing wrong with ReFactoring. -- JonathanTang