Are static anonymous classes definitely wrong in Java? - java

I've read elsewhere that a static anonymous class doesn't make sense - that all anonymous classes should be tied to an instance of the enclosing type. But the compiler let's you do it. Here's an example:
class Test {
/*
* What's the difference at between
* Test.likeThis and Test.likeThat?
*/
// This is obviously okay:
private static final class LikeThat {
#Override
public String toString() { return "hello!"; }
}
public static Object likeThat = new LikeThat();
// What about this - is it really any different?
public static Object likeThis = new Object() {
#Override
public String toString() { return "hello!"; }
};
}
What's going on here?

From the Java Language Specification, section 8.1.3:
An instance of an inner class I whose declaration occurs in a static context has no lexically enclosing instances. However, if I is immediately declared within a static method or static initializer then I does have an enclosing block, which is the innermost block statement lexically enclosing the declaration of I.
Your anonymous class (the one likeThis is an instance of) occurs in a static context, so it is not tied to an enclosing instance. However, it seems that it can refer to final variables of its enclosing block (see the rest of section 8.1.3, they give an example).
Btw, your wording is a bit deceptive, you're actually referring to a static instance of an anonymous class (it's the instance that's static, not the class).

I see nothing wrong with static anonymous classes

Like anything in any language you should just consider why you're doing it. If you've got alot of these instances then I'd question the design decisions, but it doesn't necessarily means it's a pattern that should never be followed.
And of course, always consider the testability of the class and whether you can provide a test double if the need arises

I don't think they have no sense. If you don't need reference to enclosing object then it's better to leave it static. Later it can evolve in separate class with ease.
Wide-spread enum idiom (pre Java 5) used similar approach with anonymous static inheritors of enum class. Probably, now it is better stick to Java 5 enum for this case.
If you are able to find adequate real-world application for anonymous static classes - why not to use them?

I do this all the time. It's especially handy for special-case implementations of utility interfaces, e.g.:
/** A holder for {#link Thing}s. */
public interface ThingsHolder {
/** A {#link ThingsHolder} with nothing in it. */
public static final ThingsHolder EMPTY_HOLDER = new ThingsHolder() {
#Override
public Iterable<Thing> getThings() {
return Collections.emptySet();
}
};
/** Provides some things. */
Iterable<Thing> getThings();
}
You could create a private static inner class called EmptyHolder, and maybe in some cases that would make the code more readable, but there's no reason you have to do it.

According to this answer which references the JLS, anonymous classes are never static, but when created in a "static context" they have no "enclosing instance".
That said,
They give the same error at compile time if you try to reference Test.this (non-static variable this cannot be referenced from a static context)
At runtime, the only obvious difference between the Class objects (apart from name) is that Test$1 is an "anonymous class" and Test$LikeThat is a "member class". Both of them have an enclosing class; neither of them have an enclosing constructor or method. (I only checked the likely-looking methods; there may be other differences.)
EDIT: According to getModifiers(), Test$1 is static and Test$LikeThat is static final! According to the language spec, Test$1 should actually be final. Hmm...
According to javap -c -verbose -s -private -l,
Test$1 specifies an "EnclosingMethod" (probably Test's static initializer?)
Test$LikeThat has an extra entry under "InnerClass" (#12; //class Test$1) and a curious constructor Test$LikeThat(Test$1). This appears to happen because LikeThat is private which makes the constructor private, so the compiler generates a "trampoline" to allow it to be called from Test.
If you remove the private, they appear to compile to roughly the same thing apart from the EnclosingMethod entry.
Test$1 does not have the field final Test this$0; that it would if it was defined in a non-static context.

Seems perfectly legitimate to me. Since the anonymous class is static it won't have a reference to any enclosing class, but there should be no evil consequences from that.
Well, other than being a hidden singleton object, that's pretty evil.

Of course they are not. I always use static nested classes, unless I need the implicit association to the enclosing object.
In java terminology nested class := a class which is declared within another class (or interface). Inner classes are those nested classes which have an associated instance from the enclosing class. (Nonstatic member classes, local classes, anonymous classes).
The implicit association can prevent garbage collection sometimes.

These can be very convenient because of possibility to make circular references:
class A
{
public static final A _1 = new A() {
public A foo()
{
return _2;
}
};
public static final A _2 = new A() {
public A foo()
{
return _1;
}
};
}
Creation of several objects which are holding references to each other can be very awkward without usage of anonymous classes.

Related

Difference between Interface declared in Class and Interface declared as a file [duplicate]

I have just found a static nested interface in our code-base.
class Foo {
public static interface Bar {
/* snip */
}
/* snip */
}
I have never seen this before. The original developer is out of reach. Therefore I have to ask SO:
What are the semantics behind a static interface? What would change, if I remove the static? Why would anyone do this?
The static keyword in the above example is redundant (a nested interface is automatically "static") and can be removed with no effect on semantics; I would recommend it be removed. The same goes for "public" on interface methods and "public final" on interface fields - the modifiers are redundant and just add clutter to the source code.
Either way, the developer is simply declaring an interface named Foo.Bar. There is no further association with the enclosing class, except that code which cannot access Foo will not be able to access Foo.Bar either. (From source code - bytecode or reflection can access Foo.Bar even if Foo is package-private!)
It is acceptable style to create a nested interface this way if you expect it to be used only from the outer class, so that you do not create a new top-level name. For example:
public class Foo {
public interface Bar {
void callback();
}
public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
public void callback() {...}
});
The question has been answered, but one good reason to use a nested interface is if its function is directly related to the class it is in. A good example of this is a Listener. If you had a class Foo and you wanted other classes to be able to listen for events on it, you could declare an interface named FooListener, which is ok, but it would probably be more clear to declare a nested interface and have those other classes implement Foo.Listener (a nested class Foo.Event isn't bad along with this).
Member interfaces are implicitly static. The static modifier in your example can be removed without changing the semantics of the code. See also the the Java Language Specification 8.5.1. Static Member Type Declarations
An inner interface has to be static in order to be accessed. The interface isn't associated with instances of the class, but with the class itself, so it would be accessed with Foo.Bar, like so:
public class Baz implements Foo.Bar {
...
}
In most ways, this isn't different from a static inner class.
Jesse's answer is close, but I think that there is a better code to demonstrate why an inner interface may be useful. Look at the code below before you read on. Can you find why the inner interface is useful? The answer is that class DoSomethingAlready can be instantiated with any class that implements A and C; not just the concrete class Zoo. Of course, this can be achieved even if AC is not inner, but imagine concatenating longer names (not just A and C), and doing this for other combinations (say, A and B, C and B, etc.) and you easily see how things go out of control. Not to mention that people reviewing your source tree will be overwhelmed by interfaces that are meaningful only in one class.So to summarize, an inner interface enables the construction of custom types and improves their encapsulation.
class ConcreteA implements A {
:
}
class ConcreteB implements B {
:
}
class ConcreteC implements C {
:
}
class Zoo implements A, C {
:
}
class DoSomethingAlready {
interface AC extends A, C { }
private final AC ac;
DoSomethingAlready(AC ac) {
this.ac = ac;
}
}
To answer your question very directly, look at Map.Entry.
Map.Entry
also this may be useful
Static Nested Inerfaces blog Entry
Typically I see static inner classes. Static inner classes cannot reference the containing classes wherease non-static classes can. Unless you're running into some package collisions (there already is an interface called Bar in the same package as Foo) I think I'd make it it's own file. It could also be a design decision to enforce the logical connection between Foo and Bar. Perhaps the author intended Bar to only be used with Foo (though a static inner interface won't enforce this, just a logical connection)
If you will change class Foo into interface Foo the "public" keyword in the above example will be also redundant as well because
interface defined inside another interface will implicitly public
static.
In 1998, Philip Wadler suggested a difference between static interfaces and non-static interfaces.
So far as I can see, the only difference in making an
interface non-static is that it can now include non-static inner
classes; so the change would not render invalid any existing Java
programs.
For example, he proposed a solution to the Expression Problem, which is the mismatch between expression as "how much can your language express" on the one hand and expression as "the terms you are trying to represent in your language" on the other hand.
An example of the difference between static and non-static nested interfaces can be seen in his sample code:
// This code does NOT compile
class LangF<This extends LangF<This>> {
interface Visitor<R> {
public R forNum(int n);
}
interface Exp {
// since Exp is non-static, it can refer to the type bound to This
public <R> R visit(This.Visitor<R> v);
}
}
His suggestion never made it in Java 1.5.0. Hence, all other answers are correct: there is no difference to static and non-static nested interfaces.
In Java, the static interface/class allows the interface/class to be used like a top-level class, that is, it can be declared by other classes. So, you can do:
class Bob
{
void FuncA ()
{
Foo.Bar foobar;
}
}
Without the static, the above would fail to compile. The advantage to this is that you don't need a new source file just to declare the interface. It also visually associates the interface Bar to the class Foo since you have to write Foo.Bar and implies that the Foo class does something with instances of Foo.Bar.
A description of class types in Java.
Static means that any class part of the package(project) can acces it without using a pointer. This can be usefull or hindering depending on the situation.
The perfect example of the usefullnes of "static" methods is the Math class. All methods in Math are static. This means you don't have to go out of your way, make a new instance, declare variables and store them in even more variables, you can just enter your data and get a result.
Static isn't always that usefull. If you're doing case-comparison for instance, you might want to store data in several different ways. You can't create three static methods with identical signatures. You need 3 different instances, non-static, and then you can and compare, caus if it's static, the data won't change along with the input.
Static methods are good for one-time returns and quick calculations or easy obtained data.

Java inner class with a static method

I know this question is some kind plain but i really want to know why instead of going to the documentation suppose i have class like this.
public class OuterClass{
public static void main(String[] args)throws Exception{
System.out.println(OuterClass.InnerClass.yearOfBorn);//works ok
System.out.println(OuterClass.InnerClass.returnYearOfBorn());//not works
System.out.println(OuterClass.InnerClass.returnYearOfBornAsPublic());//not works
}
private final class InnerClass{
private static final int yearOfBorn=13;
private static int returnYearOfBorn(){
return yearOfBorn;
}
public static int returnYearOfBornAsPublic(){
return yearOfBorn;
}
}
}
Both static method is throwing a error stating that
modifier 'static' is only allowed in constant variable declarations
I know that the docs states that
This is described in the Java Language Specification Section §8.1.3
8.1.3 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).
But my question what is the diff calling a simple value or property vs calling a static method not matter if is public or private?. Why calling a property is possible but not a method.
Thanks.
Non-static inner classes have something special.
static inner classes do not have it. top-level classes don't have it. any inner interface or enum doesn't have it.
That special thing is an invisible field.
This invisible field is of type Outer, and it is final. It is initialized as first thing in its constructor, and, yes, EVERY constructor of a non-static inner class has a magic invisible parameter, of type Outer, to serve as this field.
So, when you write:
public class Outer {
public class Inner {
}
}
The compiler will compile this code as if you actually wrote:
public class Outer {
public static class Inner {
private final Outer I_AM_MAGIC;
public Inner(Outer outer) {
this.I_AM_MAGIC = outer;
}
}
}
You can see this hidden magic using the javap decompilation tool; pass in -verbose and -private and you'll see these. The reason this magic exists is that you can invoke instance methods of your outer from within your inner, but.. on what instance are you calling these outer methods? On that hidden instance!
Note that this exotic, seemingly weird code: someOuter.new Inner() is in fact legal java code. When calling new Inner() from within a non-static context in Outer, the this instance is passed as invisible parameter to that constructor, but if you're not there, the code simply does not compile at all... unless you use the outer.new Inner() syntax.
The reason the compiler will stop you from adding static methods to Inner is that it was believed to lead to some confusion. Basically, the answer to your question is: "No good reason.. just... the spec says that a java compiler must not allow it, therefore, javac does not allow it".
Note that in actual fact these non-static inner classes are the confusing thing. I strongly suggest you teach yourself to ALWAYS make your inner classes static unless you really know what you're doing. And even then, think twice. Then think twice again. Then maybe consider making a non-static inner class.

Are classes in Java `static` or `non-static`?

Are classes in Java static or non-static?
Static applies only to blocks, methods and class member variables. There's no meaning in having a Class Static, although an inner class can be static member of its enclosing class. Refer nested classes.
Classes are not static. only inner classes can be marked as static
public class NotStatic
{
static class StaticClass
{
}
}
That is the only type that can be static.
Edit:
public class NotAStaticClass
{
private static int foo;
public static int getFoo()
{ return foo; }
}
How will you statically instantiate this class? Answer, you cannot. You must still utilize the new operator.
NotAStaticClass s1 = new NotAStaticClass();
Were you perhaps asking if Java is a statically typed language? If so, then the answer is yes. See Wikipedia on Static Typing
Are you taking about Static inner classes or Static Methods or Static Variables ?
As Best practice avoid using static in following cases
Avoid using Static in MultiThreaded Env.
Avoid having Static methods in your Business logic layer, if not you may lose the
advantages of OOPs such as inheritance, runtime polymorphism.
Concept of something being static is to get initialized only once i.e have only one copy in memory.. The same copy can be used whenever we want without creating another copy in memory again. So Classes being templates are not static ...
Classes cannot be static. Only methods, blocks, and variables within a class can be static, but not the class itself.

static class in java

How do I declare a static class in java? eclipse wants me to remove "static" from the declaration.
static public class Constants {
First to answer your question:
Only a Nested class can be declared static. A top level class cannot declared be static.
Secondly, Inner class is a nested class that is not explicitly declared static. See the java language spec. So contrary to some answers here, Inner classes cannot be static
To quote an example from the spec:
class HasStatic{
static int j = 100;
}
class Outer{
class Inner extends HasStatic{
static final int x = 3; // ok - compile-time constant
static int y = 4; // compile-time error, an inner class
}
static class NestedButNotInner{
static int z = 5; // ok, not an inner class
}
interface NeverInner{} // interfaces are never inner
}
If by 'static' you mean 'can have only static members', there's no such thing in Java.
Inner classes (and only them) can be static, but that's a different concept. Inner static classes can still have instance members.
Eclipse complains correctly, your code won't compile as Top level class can't be declared as static.
You need to first understand what static class means.
static class :
Top level class can't be declared as static. Only Member and Nested top-level classes can be defined as static.
You declare member classes when you want to use variables and methods of the containing class without explicit delegation. When you declare a member class, you can instantiate that member class only within the context of an object of the outer class in which this member class is declared. If you want to remove this restriction, you declare the member class a static class.When you declare a member class with a static modifier, it becomes a nested top-level class and can be used as a normal top-level class as explained above.
nested top-level class is a member classes with a static modifier. A nested top-level class is just like any other top-level class except that it is declared within another class or interface. Nested top-level classes are typically used as a convenient way to group related classes without creating a new package.
Also check when should we go for static class,variables and methods in java
As you have already been told from the other comments, classes cannot be declared static. However there are alternatives to this problem.
The most simple one is to precede all member variables and methods with the static modifier. This essentially does what you want.
A slightly more involved alternative is to make the class a singleton. This is a class in which through the use of a private constructor, and an instanceOf() method, or just an Enum, you can only have one instance of that class. Semantically and syntactically you treat that instance as an ordinary instance of whatever particular class you are making a singleton, but you can only have a single instance of that class, which you retrieve via SomeObject.instanceOf(), or in an Enum implementation, SomeObject.INSTANCE.
You would normally use Enums to implement this, minus the edge cases where you are extending another class.
For more complete information on singletons visit the link below.
Design Patterns in Java - Singleton
There is no direct equivalent of C# static classes in Java, but the closest thing in my opinion is an empty enum, which might seem weird at first, but makes sense the more you think about it. An enum in Java (unlike in C#) is essentially a set of singleton instances that all implement the same abstract base class and interfaces. The quickest and safest way to make a normal singleton in Java is like so:
enum Foo {
INSTANCE;
public Bar doSomething(Baz baz) {
return Bar.fromBaz(baz); // yadda yadda
}
}
So since we are dealing with sets of singletons, it make sense that we can have an empty set. And an empty set means there can be no instances. This is conceptually the same as a static class in C#.
enum MyUtilities {
;
static Bar doSomething(Baz baz) {
return Bar.fromBaz(baz); // yadda yadda
}
static final String SOME_CONSTANT = "QUX";
}
This is great because you won't lose test coverage because of hard to test private constructors in a final class, and the code is cleaner than a final class with an empty private constructor.
Now, if the static classes are meant to all work on a single Interface and you have control of that Interface, then you should implement the static methods on that Interface itself (something you can't do in C#).
All top level classes are implicitly static, meaning they can be accessed by everybody. So it makes sense only to make inner classes optionally static.

Why does Java prohibit static fields in inner classes?

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.

Categories

Resources