Is static inner class thread safe inside another java class? - java

For collection of smaller helper utility classes, I have created a general class MyUtils:
// MyUtils.java
public final class MyUtils
{
public static class Helper1 {};
public static class Helper2 {};
//...
}
This helper classes from inside MyUtils will be used in the other files of the package:
// MyClass1.java
public class MyClass1
{
private MyUtils.Helper1 help1 = new MyUtils.Helper1();
public void method ()
{
private MyUtils.Helper2 help2 = new MyUtils.Helper2();
}
}
To let them accessible, I have made them static inside MyUtils (which doesn't have any data/function member of its own). My code is thread safe before creating MyUtils.
My worry is, by making these inner classes staticwill they remain thread safe, when their multiple instances will exist across the files ? Or is their any bad implication am I missing due to making them static ?
Edit: I am not touching any shared variable inside the helper classes. My only concern was that will the instance of the static classes be thread safe (since they are static).

If you're asking whether these is any bad implication of going from:
public class Helper1 {}
...to:
public class MyUtils {
public static class Helper1 {}
}
Then no, there is not. The static keyword in this case is just "promoting" the nested inner class to a top-level class, so that you can instantiate it without needing an enclosing instance of MyUtils. Here is a passable article on the subject:
http://www.javaworld.com/javaworld/javaqa/1999-08/01-qa-static2.html
In essence, doing public static class X on a nested inner-class is the same as doing public class X in a standard top-level class.

There is no meaning to a "class" itself being thread-safe or not thread safe. Therefore, whether or not it is static is irrelevant.
When someone refers to a class being thread-safe or not thread-safe, they really mean that the functionalities provided by that class are thread-safe or not. Accordingly, it's what the inner classes do themselves that actually makes the difference.
There's nothing inherent about methods that make them unsafe to be reentrant. Problems arise when you start accessing shared variables, etc. So, for example, a member of the class accessed by the methods needs to be synchronized appropriately. But if the methods don't store any state, etc., then there's nothing stopping you from using them across multiple threads.
Hope that helps.

You will need to guard the access to help1 since this is an instance level (shared) variable.
While help2 is safe if you dont allow it to skip the method.
There is nothing special about the static classes and instance created out of it.
Same rules of thread safety applies to instances of static classes also which applies to normal cases.

static methods and inner classes don't have any access to the variables of their dynamic counter part, and consequently can't use monitors/synchronize on an instance of their parent class. Of course this doesn't mean that declaring them and using them is inherently non-thread safe. It's just that if you need to synchronize any of those static methods on an instance of the parent class, then you need to be sure that you synchronize/lock before entering them or else you must explicitly pass a reference to a parent instance into them.

I have got the answer. Making MyUtils an interface is more cleaner design, as I can get away with the static identifienr from the helper classes

Related

Compile time constants in inner classes [duplicate]

class OuterClass {
class InnerClass {
static int i = 100; // compile error
static void f() { } // compile error
}
}
Although it's not possible to access the static field with OuterClass.InnerClass.i, if I want to record something that should be static, e.g. the number of InnerClass objects created, it would be helpful to make that field static. So why does Java prohibit static fields/methods in inner classes?
EDIT: I know how to make the compiler happy with static nested class (or static inner class), but what I want to know is why java forbids static fields/methods inside inner classes (or ordinary inner class) from both the language design and implementation aspects, if someone knows more about it.
what I want to know is why java forbids static fields/methods inside inner classes
Because those inner classes are "instance" inner classes. That is, they are like an instance attribute of the enclosing object.
Since they're "instance" classes, it doesn't make any sense to allow static features, for static is meant to work without an instance in the first place.
It's like you try to create a static/instance attribute at the same time.
Take the following example:
class Employee {
public String name;
}
If you create two instances of employee:
Employee a = new Employee();
a.name = "Oscar";
Employee b = new Employee();
b.name = "jcyang";
It is clear why each one has its own value for the property name, right?
The same happens with the inner class; each inner class instance is independent of the other inner class instance.
So if you attempt to create a counter class attribute, there is no way to share that value across two different instances.
class Employee {
public String name;
class InnerData {
static count; // ??? count of which ? a or b?
}
}
When you create the instance a and b in the example above, what would be a correct value for the static variable count? It is not possible to determine it, because the existence of the InnerData class depends completely on each of the enclosing objects.
That's why, when the class is declared as static, it doesn't need anymore a living instance, to live itself. Now that there is no dependency, you may freely declare a static attribute.
I think this sounds reiterative but if you think about the differences between instance vs. class attributes, it will make sense.
The idea behind inner classes is to operate in the context of the enclosing instance. Somehow, allowing static variables and methods contradicts this motivation?
8.1.2 Inner Classes and Enclosing Instances
An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).
InnerClass cannot have static members because it belongs to an instance (of OuterClass). If you declare InnerClass as static to detach it from the instance, your code will compile.
class OuterClass {
static class InnerClass {
static int i = 100; // no compile error
static void f() { } // no compile error
}
}
BTW: You'll still be able to create instances of InnerClass. static in this context allows that to happen without an enclosing instance of OuterClass.
From Java 16 onwards, this is no longer the case. Quoting from JEP 395 (on finalizing records):
Relax the longstanding restriction whereby an inner class cannot declare a member that is explicitly or implicitly static. This will become legal and, in particular, will allow an inner class to declare a member that is a record class.
Indeed, the following code can be compiled with Java 16 (tried with 16.ea.27):
public class NestingClasses {
public class NestedClass {
static final String CONSTANT = new String(
"DOES NOT COMPILE WITH JAVA <16");
static String constant() {
return CONSTANT;
}
}
}
Actually, you can declare static fields if they are constants and are written in compile time.
class OuterClass {
void foo() {
class Inner{
static final int a = 5; // fine
static final String s = "hello"; // fine
static final Object o = new Object(); // compile error, because cannot be written during compilation
}
}
}
class Initialization sequence is a critical reason.
As inner classes are dependent on the instance of enclosing/Outer class, so Outer class need to be initialized before the initialization of the Inner class.
This is JLS says about class Initialization. The point we need is, class T will be initialize if
A static field declared by T is used and the field is not a constant variable.
So if inner class have an static field accessing that will cause initializing the inner class, but that will not ensure that the enclosing class is initialized.
It would violate some basic rules. you can skip to the last section (to two cases) to avoid noob stuff
One thing about static nested class, when some nested class is static it will behave just like a normal class in every way and it is associated with the Outer class.
But the concept of Inner class/ non-static nested class is it will be associated with the instance of outer/enclosing class. Please note associated with instance not the class.
Now associating with instance clearly means that (from the concept of instance variable) it will exist inside a instance and will be different among instances.
Now, when we make something static we expect it will be initialized when the class is being loaded and should be shared among all instances. But for being non-static, even inner classes themselves (you can definitely forget about instance of inner class for now) are not shared with all instance of the outer/enclosing class (at least conceptually), then how can we expect that some variable of inner class will be shared among all the instance of the inner class.
So if Java allow us to use static variable inside not static nested class. there will be two cases.
If it is shared with all the instance of inner class it will violate the concept of context of instance(instance variable). It's a NO then.
If it is not shared with all instance it will violate the the concept of being static. Again NO.
Here is the motivation that I find best suitable for this "limit":
You can implement the behavior of a static field of an inner class as an instance field of the outer object;
So you do not need static fields/methods.
The behaviour I mean is that all inner class instances of some object share a field(or method).
So, suppose you wanted to count all the inner class instances, you would do:
public class Outer{
int nofInner; //this will count the inner class
//instances of this (Outer)object
//(you know, they "belong" to an object)
static int totalNofInner; //this will count all
//inner class instances of all Outer objects
class Inner {
public Inner(){
nofInner++;
totalNofInner++;
}
}
}
In simple words, non-static inner classes are instance variable for outer class, and they are created only when an outer class is created and an outer class object is created at run-time while static variables are created at class loading time.
So non-static inner class is runtime thing that's why static not the part of a non-static inner class.
NOTE: treat inner classes always like a variable for an outer class they may be static or non-static like any other variables.
Because it would cause ambiguity in the meaning of "static".
Inner classes cannot declare static members other than
compile-time constants. There would be an ambiguity about the meaning
of “static.” Does it mean there is only one instance in the virtual
machine? Or only one instance per outer object? The language designers
decided not to tackle this issue.
Taken from "Core Java SE 9 for the Impatient" by Cay S. Horstmann. Pg 90 Chapter 2.6.3
In the Java language designers' own words:
Since nested classes were first introduced to Java, nested class
declarations that are inner have been prohibited from declaring static
members... It simplifies the language's task of resolving and
validating references to in-scope variables, methods, etc.
There was never any particularly grand conceptual or philosophical reason to prohibit this.
Simplifying things for the language was deemed an insufficient reason to continue to maintain this restriction. Along with the introduction of records in Java 16, they made the decision to relax the restriction.
Class Inner will be initialize if a static field declared by Inner is used and the field is not a constant variable.
class Outer{
class Inner{
static Inner obj = new Inner();
}
public static void main(String[] args){
Inner i = Inner.obj; // It woulds violate the basic rule: without existing Outer class Object there is no chance of existing Inner class Object.
}
}
I guess it's for consistency. While there doesn't seem to be any technical limitation for it, you wouldn't be able to access static members of the internal class from the outside, i.e. OuterClass.InnerClass.i because the middle step is not static.

Why have public methods inside private classes?

I was going through a part of a code which was something like this
// compare points according to their polar radius
public static final Comparator<Point2D> R_ORDER = new ROrder();
.
.
.
private static class ROrder implements Comparator<Point2D> {
public int compare(Point2D p, Point2D q) {
double delta = (p.x*p.x + p.y*p.y) - (q.x*q.x + q.y*q.y);
if (delta < 0) return -1;
if (delta > 0) return +1;
return 0;
}
}
Why do we have such public methods inside private static classes. What harm would it do if i made ROrder
Non-Static
Public
ROrder Non-Static
By making it non-static you will need the instance of the container class to create the instance of ROder, which maybe due to the design of the class would not make logic. You should keep class non-static only when you really need the instance of outer class to get the instance of inner class.
ROrder Public
Again because they wanted to restrict the use of ROrder outside the context of this class. They did not want any client code or other code to freely create instances of ROrder, as they would not be of any use.
Why do we have such public methods inside private static classes.
In this case because you are implementing an interface Comparator and you will pass this comparator for other uses, such as sorting and you would want the Collections class to have the visibility of compare method, so the method has to be public even if the class implementing the interface is private.
So this is just a logical way to enhance the readability and intent of use of the code.
Logical Use
This class wants the string to be in some format.
public class SomeClass{
private static class StringHelper{
//will do the task of parsing and validating that string object
}
}
Now in this case you would not want to keep StringHelper class public, as its use is too localized to be reused. So you would rather emphasize that by keeping it private. And there can be methods that are public if StringHelper implemented some interface.
UPDATE:
You should keep class non-static only when you really need the
instance of outer class to get the instance of inner class.
On that I think the answer can be too broad, but I would try to explain in short. By that what I mean was that if the inner class object shares some state of the outer object on which its processing is dependent, then you will need the object of outer class to share its state with the inner class object, but if the inner class instance is independent of the state of outer class, then it is safe to keep the inner class static.
This class implements Comparator and so must implement its methods. The implementation methods can't be static. Also, since interface methods are implicitly public, they must be declared public, regardless of the containing class's visibility. Try not doing so and it will fail to compile. This is certainly the reason it is declared public here -- it can't not be.
This is true regardless of whether the containing class is static or public. Here, it could be either of those things and the method inside would still have to be public and non-static.
Other methods that don't implement an interface could be private, and, logically probably should inside a private class as there would be no point in declaring it otherwise -- but it would be allowed by Java syntax.
All private members (fields, classes, whatever) are only visible inside the class. So, it doesn't matter what visibility you give a method of a private class - all methods will only be visible inside the containing class, because the class itself is private.
If the inner class implements an interface or extends a class, overridden methods may not have less visibility than the declaration in the super type, so that's one reason to have public methods in a private inner class.
However, although the syntax allows private classes to have public methods, it won't increase the visibility of those methods sufficiently to be visible outside the containing class. There are several examples in java of modifiers being legal but having no effect, such as inner interfaces being implicitly static (whether or not the static keyword is used).
This class is private because developer did not want to ROrder be instantiated in other place. But an instance can be accessed through the constant R_ORDER from other classes.
The method is public for two reason : first, compare is defined in the Comparator interface. Second, as R_ORDER is accessible from other classes, it is more than convenient to be able to call a method on this object. In this case, it is compare.
Finally, if the class was not static, it would keep a reference to the parent class, which is almost always not needed

What are the purposes of inner classes

I am reviewing the concept of inner classes in java. so far from what I've understood and applied java inner classes has a link or access to the methods and fields of its outer/ enclosing class.
My Question:
When should create or define an inner class?
are inner classes considered to be called as "Helper classes" ?
What are the indicators for you to make an inner class and what's their other purpose?
Inner classes are best for the purpose of logically grouping classes that are used in one-place. For example, if you want to create class which is used by ONLY enclosing class, then it doesn't make sense to create a separate file for that. Instead you can add it as "inner class"
As per java tutorial:
Compelling reasons for using nested classes include the following:
It is a way of logically grouping classes that are only used in one
place.
It increases encapsulation.
It can lead to more readable and maintainable code.
A classic use for an inner class is the implementation of an iterator inside a container (ArrayList, for example - look for class Itr). All the container wants to expose to the rest of the world is an Iterator. However, it has to create some concrete implementation of that iterator, possibly familiar with the internals of the container. Using an inner class hides the implementation, while keeping it close to the container's implementation. And being inner (i.e. non-static), it is bound to a specific instance of that container, which lets it access private container members.
There are a few types of inner classes - non-static nested class, local classes and anonymous classes. Each one has a somewhat different purpose, so when asking about an inner class, you should specify what kind are you talking about.
Assuming you're referring to non-static inner classes, I'd say the reason to use them is the same as using regular classes (namely abstraction and dividing code into logical units), but there's no reason to make this use of classes visible to the rest of the world. You can also make nested classes public, of course, in which case you'd make them nested instead of independent in order to express their tight relation with the outer class.
See the Java tutorial for the main reasons.
If by "helper class" you mean something for internal use only, then no, not necessarily. You might want to do something like
class Outer {
private static class Inner implements InterestingInterface {
// whatever
}
public InterestingInterface make_something_interesting() {
return new Inner();
}
}
Here, Inner is not a "helper class" in the sense that the outside world does get to see instances of it, but its implementation is entirely hidden -- the outside world only knows it gets some object that implements InterestingInterface.
As a general rule, objects should be designed for a single responsibility (Highly cohesive). In other words, any object designed well, should perform a single coherent task. This would be considered best practice for object orientated design.
Sometimes, however, a developer may design a class that requires a separate specialized class in order to work. This separate specialized class could be considered a helper class.
If the helper class is not used by any other class, then it would be considered a prime candidate as an inner class
As elicited by ncmathsadist above, an example of inner class use would be in the implementation of Event handlers.
For example, in designing a graphical user interface (GUI), a developer may have created a button that performs a particular task after the user presses it.
The button would need an event handler which listens for when that particular button is pressed.
In this case, creating the event handler for the button as an inner class would be best practice as the inner class would not be utilized anywhere else other than with the specific button within the GUI class.
One purpose of inner classes is to attach listeners. For example, suppose you have a JMenuItem. You can make it quit your app as shown in this code:
JMenuItem quitItem = new JMenuItem("Quit");
quitItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//cleanup code before exiting
System.exit(0);
}
});
You may also want a class to have access to outer class state variables which is entirely subservient to that class. For example, consider writing a simple color calculator. It might have a text area into which you type a hex code. When you hit enter, you want a JPanel to display the color. Here is a crude outline of what you might do.
public class ColorCalc extends JPanel implements Runnable
{
Color displayedColor;
JTextArea colorEnterArea;
public ColorCalc()
{
displayedColor = Color.white
colorEnterArea = new JTextArea();
}
public void run()
{
//build GUI here
}
public static void main(String[] args)
{
ColorCalc cc = new ColorCalc();
javax.swing.SwingUtilities.invokeLater(cc);
}
//subservient inner class with access to outer class state variable.
class ColorPanel extends JPanel
{
public void paintComponent(Graphics g)
{
g.setColor(displayedColor);
g.fillRect(0,0,getWidth(), getHeight());
}
}
}
This is a style question. Anything that can be done with an inner class can also be done as a as series of external classes. Inner classes are especially useful for classes that are lightweight or tightly bound to the enclosing class. For example, a comparator is frequently both these things. It needs intimate knowledge of the implementation of the class, and may only be a few lines long. It may be an ideal candidate as an internal class.
If you find that there is enough code which could be better done by class as class provides us to specify stats and
behavior with fields and methods and you don't want this class needs to be used outside of enclosing class. you should use inner class.
Here the inner class is hidden from the outside world.
Inner class can access the private member of enclosing class which provides us encapsulation.
Let me give example..
Suppose you want to set the gear to cycle and you have a business rule like there are only up to 6 gears.
So you can create Inner Class Cycle which would have a method to set the gear.
That method has some validation which are checked before setting gear.like the cycle is running...gear number is less than 6...
best example is event handling code uses inner classes(sometimes anonymous inner classes) to create events and listeners without creating separate Event Object and Event Listener classes for your event..
The inner class used for grouping classes logic, for example, if you have class B and this class used only at class A, So it is better to put class B as an inner class at class A, as this will give readability and reusability for your code.
Happy code :)
Adding from my personal notes, for future visitors:
Sources: https://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html
Lets say you have a type and its a class, called OuterClass, in a package called "com.custom.classes".
Then here is how you begin to need an inner class or static class:
Case 1:
you need to package a group of classes
but also kind of need certain global variables exposed to all these classes at that package level
you understand you can do no such things with packages but realise that you could achieve this with inheritance, where the parent class members can act as global variables that become available for all of its child class instances.
but you don't like the idea that you need to inherit the parent class and also that you need to instantiate the child class to access the global variables. Thats like asking to buy a coffee shop in order to have a coffee.
and so you realise that you can create an OuterClass with the static members and house all the classes in this OuterClass as inner class or static class as needed and lo! The OuterClass static members become available as global variables for these nested classes and you could even access them without instantiating them.
This code should explain better
public class InnerClassTester{
public static void main(String []args){
// without the need to instantiate any class
// static class without instantiation
System.out.println(OuterClass.NestedStaticClass1.incrGlobalNum()); // outputs 1
// static class instantiated
OuterClass.NestedStaticClass2 koolObj = new OuterClass.NestedStaticClass2();
// works with instantiation as well
System.out.println(koolObj.incrGlobalNum()); // outputs 2
// inner classes always need to be instantiated
// and they can only be instantiated from within an instance of outer class
// think of them as instance member of outer class and this would make sense
OuterClass.NestedInnerClass1 koolObj2 = new OuterClass().new NestedInnerClass1();
// works with inner classes as well
System.out.println(koolObj2.incrGlobalNum()); // outputs 3
}
}
class OuterClass{
// global variable thats only accessible for select classes (or nested classes)
// we also learn a purpose for private static fields
private static int privateGlobalValue = 0;
// classes to be grouped
// static class
public static class NestedStaticClass1{
// no need to instantiate this class to access/update the global value
public static int incrGlobalNum(){
return ++privateGlobalValue;
}
}
public static class NestedStaticClass2{
// instantiate and still manipulate the global value
public int incrGlobalNum(){
return ++privateGlobalValue;
}
}
// inner class
public class NestedInnerClass1{
// instantiate and still manipulate the global value
public int incrGlobalNum(){
return ++privateGlobalValue;
}
}
}
Does this remind you of closures in Javascript ? :)
Most applications of nested classes see it being applied on basis of design decisions. What that means is, every case of a nested class can be replaced with other designs.
But having said that, it is also true that we can also replace the inheritance pattern with composition pattern (and it is gaining momentum lately) although an inheritance pattern is definitely better when the dependencies between the classes is so much so that composing the dependencies entirely would be ugly.
Case 2:
you need to implement 2 interfaces, IShark and IMosquito, with the same signature, a public bite method, on the OuterClass.
but you want to display 2 different messages since a shark's bite is a tad different from that of a mosquito's.
however you know that's not possible since only one bite method can be implemented
you know you can create 2 different classes in the same package that implement either interfaces and also implement separate bite methods and have them composed in OuterClass.
but you wanted to get it done within OuterClass because it was your design decision to encapsulate the bite behaviour within it, maybe because there was a dependency on a private variable within the class.
soon you realise you can implement both the interfaces via private static inner classes and make it appear to the outside world as though it was composed.
Take a look at this code:
// no additional classes in the package
public class InterfaceTester{
public static void main(String []args){
// same class returns 2 instances - both compliant to
// either interfaces and yet different output
IShark shark = OuterClass.getSharkInstance();
System.out.println(shark.bite()); // outputs "Die fast bosedk!"
IMosquito mosquito = OuterClass.getMosquitoInstance();
System.out.println(mosquito.bite()); // outputs "Die slow bosedk!"
}
}
interface IShark{
public String bite();
}
interface IMosquito{
public String bite();
}
class OuterClass implements IShark{
// dependency of inner class on private variable
private static String dieSlow = "Die slow bosedk!";
private static String dieFast = "Die fast bosedk!";
private static OuterClass outerInst;
private static InnerClass innerInst;
// private constructor to stop regular instantiation
private OuterClass(){}
// get a shark !
public static IShark getSharkInstance(){
return outerInst != null ? outerInst : new OuterClass();
}
// get a mosquito !
public static IMosquito getMosquitoInstance(){
return innerInst != null ? innerInst : new InnerClass();
}
// an implementation of bite
public String bite(){
return dieFast;
}
// inner class that implements the second interface
private static class InnerClass implements IMosquito{
// different implementation of bite
public String bite(){
return dieSlow;
}
}
}
These kind of design decision cases are numerous and all of the answers above list several such cases. So it would not be wrong to think that this feature was introduced more as a new pattern than as a feature or functionality.
Conceptually inner classes can be used to represent types in the universe that would not exist without that parent type. In other words, with a language that allows inner classes, the types are all 'type definers'. A type can then be considered something that explicitly or implicitly defines new types.
For example, imagine we have a universe where "Food" can be applied to anything. Even itself. Food is a fundamental concept in our universe. We introduce a subclass of Food called Meat. Without that concept, there is no such thing as "Meat Eater". So we can (note 'can') define a nested type "Meat.Eater" (which could implement an IEater interface) and define animals as being a containment structure of lists of different IEaters.
Once we remove Meat from the universe, Meat Eater disappears to.
This same philosophy applies neatly to more abstract and technically useful arrangements such as Mementos in the Memento Design Pattern , a configuration object defined as a nested class, and other type-specific behaviours or structures.
It also increases encapsulation because inner classes can be declared private.
I would just consider that this is just a feature of language. I would not recommend to use it if we adopt OOD and obey the SOLID principle.

How to lock(sync) a static class?

I'm creating a static class which is going to hold some vectors with info.
I have to make it synchronized so that the class will be locked if someone is editing or reading from the vectors.
What is the best way to do this?
Is it enough to have a function which is synchronized inside the class like this:
public synchronized insertIntoVector(int id)
{
}
Thanks in advance :)
Firstly, you need to define exactly what you mean by "static class". At first, I thought you meant a class where all methods were static (that wasn't meant to be instantiated) - but your code snippet implies this isn't the case.
In any case, synchronized methods inside the class are equivalent to synchronized(this) if they are instance methods, or synchronized(TheContainingClassName.class) if they're static methods.
If you are either creating a non-instantiable class with all static methods, or if you are creating a class that will act as a singleton, then synchronizing every method of the class will ensure that only one thread can be calling methods at once.
Do try to ensure that your methods are atomic though, if possible; calls to different methods can be interleaved by other threads, so something like a getFoo() call followed by a setFoo() (perhaps after incrementing the foo variable) may not have the desired effect if another thread called setFoo() inbetween. The best approach would be to have a method such as incrementFoo(); alternatively (if this is not possible) you can publish the synchronization details so that your callers can manually hold a lock over the class/instance during the entire sequence of calls.
AFAIK, there's no such thing as "static class" in Java. Do you mean a class that contains only static methods? If so, then
public static synchronized void insertIntoVector(int id) {
}
synchronizes with respect to the class object, which is sufficient, if there are only static methods and all of them are synchronized.
If you mean static inner class (where the word "static" has a different meaning than in static methods), then
public synchronized void insertIntoVector(int id)
{
}
synchronizes with respect to an instance of that static inner class.

Is it possible to make anonymous inner classes in Java static?

In Java, nested classes can be either static or not. If they are static, they do not contain a reference to the pointer of the containing instance (they are also not called inner classes anymore, they are called nested classes).
Forgetting to make an nested class static when it does not need that reference can lead to problems with garbage collection or escape analysis.
Is it possible to make an anonymous inner class static as well? Or does the compiler figure this out automatically (which it could, because there cannot be any subclasses)?
For example, if I make an anonymous comparator, I almost never need the reference to the outside:
Collections.sort(list, new Comparator<String>(){
int compare(String a, String b){
return a.toUpperCase().compareTo(b.toUpperCase());
}
}
No, you can't, and no, the compiler can't figure it out. This is why FindBugs always suggests changing anonymous inner classes to named static nested classes if they don't use their implicit this reference.
Edit: Tom Hawtin - tackline says that if the anonymous class is created in a static context (e.g. in the main method), the anonymous class is in fact static. But the JLS disagrees:
An anonymous class is never abstract (§8.1.1.1). An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1). An anonymous class is always implicitly final (§8.1.1.2).
Roedy Green's Java Glossary says that the fact that anonymous classes are allowed in a static context is implementation-dependent:
If you want to baffle those maintaining your code, wags have discovered javac.exe will permit anonymous classes inside static init code and static methods, even though the language spec says than anonymous classes are never static. These anonymous classes, of course, have no access to the instance fields of the object. I don’t recommend doing this. The feature could be pulled at any time.
Edit 2: The JLS actually covers static contexts more explicitly in §15.9.2:
Let C be the class being instantiated, and let i be the instance being created. If C is an inner class then i may have an immediately enclosing instance. The immediately enclosing instance of i (§8.1.3) is determined as follows.
If C is an anonymous class, then:
If the class instance creation expression occurs in a static context (§8.1.3), then i has no immediately enclosing instance.
Otherwise, the immediately enclosing instance of i is this.
So an anonymous class in a static context is roughly equivalent to a static nested class in that it does not keep a reference to the enclosing class, even though it's technically not a static class.
I think there's a bit of confusion in the nomenclature here, which admittedly is too silly and confusing.
Whatever you call them, these patterns (and a few variations with different visibility) are all possible, normal, legal Java:
public class MyClass {
class MyClassInside {
}
}
public class MyClass {
public static class MyClassInside {
}
}
public class MyClass {
public void method() {
JComponent jc = new JComponent() {
...
}
}
}
public class MyClass {
public static void myStaticMethod() {
JComponent jc = new JComponent() {
...
}
}
}
They are catered for in the language spec (if you're really bothered, see section 15.9.5.1 for the one inside the static method).
But this quote is just plain wrong:
javac.exe will permit anonymous
classes inside static init code and
static methods, even though the
language spec says than anonymous
classes are never static
I think the quoted author is confusing the static keyword with static context. (Admittedly, the JLS is also a bit confusing in this respect.)
Honestly, all of the patterns above are fine (whatever you call them "nested", "inner", "anonymous" whatever...). Really, nobody is going to suddenly remove this functionality in the next release of Java. Honestly!
Kind of. An anonymous inner class created in a static method will obviously be effectively static because there is no source for an outer this.
There are some technical differences between inner classes in static contexts and static nested classes. If you're interested, read the JLS 3rd Ed.
Inner classes can't be static - a static nested class is not an inner class. The Java tutorial talks about it here.
anonymous inner classes are never static (they can't declare static methods or non final static fields),but if they're defined in a static context (static method or static field) they behave as static in the sense that they can't access non-static (i.e. instance) members of the enclosing class (like everything else from a static context)
On the note of making an anonymous inner class static by calling them within a static method.
This doesn't actually remove the reference. You can test this by trying to serialize the anonymous class and not making the enclosing class serializable.

Categories