Related
I have an inner class that stores the info of the controls I'm using for a game, now I want to store a static ArrayList in it that holds all the names of the controls. But I am getting this error: "Modifier static is only allowed in constant variable declarations"
private class Control{
public static ArrayList<String> keys = new ArrayList<String>();
public final String key;
public final Trigger trigger;
Control(String k, Trigger t){
key = k;
trigger = t;
keys.add(key);
}
}
Now I know this can easily be solved by taking the ArrayList out of the class and storing it in the main class. But I'd prefer to keep all the information in one class where I can access everything.
"Control.key, Control.trigger, Control.keys"
is just more elegant/readable than
"key, trigger, keys"
Or maybe I just have Obsessive–compulsive disorder, still I'd like to do it my way.
You can make the Control class static.
private static class Control {
^^^^^^
// Ok to have static members:
public static ArrayList<String> keys = new ArrayList<String>();
...
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).
Make your inner class static and it will work:
private static class Control { ...
I have an inner class in my Java class.
When I run find bugs, it recommends(warns) to make it as static.
What's the point of this warning? What's the advantage of making a inner class as static?
If the nested class does not access any of the variables of the enclosing class, it can be made static. The advantage of this is that you do not need an enclosing instance of the outer class to use the nested class.
An inner class, by default, has an implicit reference to an object of the outer class. If you instantiate an object of this from the code of the outer class, this is all done for you. If you do otherwise you need to provide the object yourself.
A static inner class does not have this.
That means it can be instantiated outside the scope of an outer class object. It also means that if you 'export' an instance of the inner class, it will not prevent the current object to be collected.
As a basic rule, if the inner class has no reason to access the outer one, you should make it static by default.
A static inner class is a semantically simpler thing. It's just like a top-level class except you have more options for visibility (e.g. you can make it private).
An important reason to avoid non-static inner classes is that they are more complex. There is the hidden reference to the outer class (maybe even more than one). And a simple name in a method of the inner class may now be one of three things: a local, a field, or a field of an outer class.
An artifact of that complexity is that the hidden reference to the outer class can lead to memory leaks. Say the inner class is a listener and could be a static inner class. As long as the listener is registered, it holds a reference to the instance of the outer class, which may in turn hold on to large amounts of memory. Making the listener static may allow the outer instance to be garbage collected.
A Non-static inner class has an implicit reference to outer class. If you make the class as static, you could save some memory and code.
Benefits of static inner classes:
Instantiation of static inner class does not rely on external class guidance, and the memory overhead of instantiation.
Static inner class does not hold external class guidance, does not affect the collection of external class, to avoid the extension of the external class in memory survival time leading to memory leakage.
We already have good answers, here are my 5 cents:
Both static and non-static inner classes are used when we need to separate logical functionalities yet using the methods and variables of the outer class. Both of the inner classes have access to the private variables of the outer class.
Advantages of static inner class:
1) static classes can access the static variables from outer class
2) static classes can be treated like an independent class
Non-static inner class:
1) cannot use static members of the outer class
2) cannot be treated like an independent class
public class NestedClassDemo {
private int a = 100;
int b = 200;
private static int c = 500;
public NestedClassDemo() {
TestInnerStatic teststat = new TestInnerStatic();
System.out.println("const of NestedClassDemo, a is:"+a+", b is:"+b+".."+teststat.teststat_a);
}
public String getTask1(){
return new TestInnerClass().getTask1();
}
public String getTask2(){
return getTask1();
}
class TestInnerClass{
int test_a = 10;
TestInnerClass() {
System.out.println("const of testinner private member of outerlcass"+a+"..."+c);
}
String getTask1(){
return "task1 from inner:"+test_a+","+a;
}
}
static class TestInnerStatic{
int teststat_a = 20;
public TestInnerStatic() {
System.out.println("const of testinnerstat:"+teststat_a+" member of outer:"+c);
}
String getTask1stat(){
return "task1 from inner stat:"+teststat_a+","+c;
}
}
public static void main(String[] args){
TestInnerStatic teststat = new TestInnerStatic();
System.out.println(teststat.teststat_a);
NestedClassDemo nestdemo = new NestedClassDemo();
System.out.println(nestdemo.getTask1()+"...."+nestdemo.getTask2());
}
}
Accessing the static inner and non-static inner class from outside:
public class TestClass {
public static void main(String[] args){
NestedClassDemo.TestInnerClass a = new NestedClassDemo().new TestInnerClass();
NestedClassDemo.TestInnerStatic b = new NestedClassDemo.TestInnerStatic();
}
}
The official java doc for static inner class can be found at https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
I found that in Java, there is a feature called static block, which includes code that is executed when a class is first loaded (I don't understand what 'loaded' means, does it mean initialized?). Is there any reason to do the initialization bit inside a static block and not in the constructor? I mean, even the constructor does the same thing, do all the necessary stuff when a class is first initialized. is there anything that the static block accomplishes which a constructor can't?
I first want to highlight one thing thing from your question:
the constructor does the same thing, do all the necessary stuff when a class is first initialized
This is incorrect. A constructor does all the initialization necessary when an instance of a class is created. No constructors execute when the class itself is first loaded into memory and initialized (unless an instance of the class happens to be created as part of the class initialization). This confusion (between initializing a class and initializing instances of the class) is probably why you are questioning the utility of static blocks.
If a class has static members that require complex initialization, a static block is the tool to use. Suppose you need a static map of some kind (the purpose is irrelevant here). You can declare it in-line like this:
public static final Map<String, String> initials = new HashMap<String, String>();
However, if you want to populate it once, you can't do that with an in-line declaration. For that, you need a static block:
public static final Map<String, String> initials = new HashMap<String, String>();
static {
initials.put("AEN", "Alfred E. Newman");
// etc.
}
If you wanted to be even more protective, you can do this:
public static final Map<String, String> initials;
static {
Map<String, String> map = new HashMap<String, String>()
map.put("AEN", "Alfred E. Newman");
// etc.
initials = Collections.unmodifiableMap(map);
}
Note that you cannot initialize initials in-line as an unmodifiable map because then you couldn't populate it! You also cannot do this in a constructor because simply calling one of the modifying methods (put, etc.) will generate an exception.
To be fair, this is not a complete answer to your question. The static block could still be eliminated by using a private static function:
public static final Map<String, String> initials = makeInitials();
private static Map<String, String> makeInitials() {
Map<String, String> map = new HashMap<String, String>()
map.put("AEN", "Alfred E. Newman");
// etc.
return Collections.unmodifiableMap(map);
}
Note, though, that this is not replacing a static block with code in a constructor as you proposed! Also, this won't work if you need to initialize several static fields in an interrelated way.
A case where a static block would be awkward to replace would be a "coordinator" class that needs to initialize several other classes exactly once, especially awkward if it involves dependency injection.
public class Coordinator {
static {
WorkerClass1.init();
WorkerClass2.init(WorkerClass1.someInitializedValue);
// etc.
}
}
Particularly if you don't want to hard-wire any dependence into WorkerClass2 on WorkerClass1, some sort of coordinator code like this is needed. This kind of stuff most definitely does not belong in a constructor.
Note that there is also something called an instance initializer block. It is an anonymous block of code that is run when each instance is created. (The syntax is just like a static block, but without the static keyword.) It is particularly useful for anonymous classes, because they cannot have named constructors. Here's a real-world example. Since (unfathomably) GZIPOutputStream does not have a constructor or any api call with which you can specify a compression level, and the default compression level is none, you need to subclass GZIPOutputStream to get any compression. You can always write an explicit subclass, but it can be more convenient to write an anonymous class:
OutputStream os = . . .;
OutputStream gzos = new GZIPOutputStream(os) {
{
// def is an inherited, protected field that does the actual compression
def = new Deflator(9, true); // maximum compression, no ZLIB header
}
};
Constructor is invoked while creating an instance of the class.
Static block is invoked when a classloader loads this class definition, so that we can initialize static members of this class.
We should not be initializing static members from constructor as they are part of class definition not object
Static initializer will run if we initialize a class, this does not require that we instantiate a class. But the constructor is run only when we make an instance of the class.
For example:
class MyClass
{
static
{
System.out.println("I am static initializer");
}
MyClass()
{
System.out.println("I am constructor");
}
static void staticMethod()
{
System.out.println("I am static method");
}
}
If we run:
MyClass.staticMethod();
Output:
I am static initializer
I am static method
We never created an instance so the constructor is not called, but static initializer is called.
If we make an instance of a class, both static initilizer and the constructor run. No surprises.
MyClass x = new MyClass();
Output:
I am static initializer
I am constructor
Note that if we run:
MyClass x;
Output: (empty)
Declaring variable x does not require MyClass to be initialized, so static initializer does not run.
The static initializer runs when the class is loaded even if you never create any objects of that type.
Not all classes are meant to be instantiated. The constructor might never be called. It might even be private.
You may wish to access static fields of the class before you run a constructor.
The static initializer only runs once when the class is loaded. The constructor is called for each object of that type you instantiate.
You can't initialize static variables with a constructor -- or at least you probably shouldn't, and it won't be particularly useful.
Especially when you're trying to initialize static constants that require significant logic to generate, that really ought to happen in a static block, not a constructor.
They're two separate things. You use a constructor to initialize one instance of a class, the static initialization block initializes static members at the time that the class is loaded.
The static block is reqly useful when you do have to do some action even if no instances is still created. As example, for initializing a static variable with non static value.
static block does different thing than constructor . Basically there sre two different concepts.
static block initializes when class load into memory , it means when JVM read u'r byte code.
Initialization can ne anything , it can be variable initialization or any thing else which should be shared by all objects of that class
whereas constructor initializes variable for that object only .
The static block is useful when you want to initialize static fields.
The static block is useful over constructors when you do have to do some action even if no instances is still created. As example, for initializing a static variable with non static value.
One way you can understand static block is;
It acts as a constructor. however, the difference between the two is
static block instantiates class or static variables while constructor is used to instantiate object variables
Consider the following class
public class Part{
String name;
static String producer;
public Part(String name){
this.name = name;
}
static {
producer = "Boeing";
}
}
objects created from this class will have producer set to Boeing but their name is different depending on the argument passed. for instance
Part engine = new Part("JetEngine");
Part Wheel = new Part("JetWheel");
Initializing static fields in the constructor is a big mistake. Yes, you can initialize static fields in the constructor. However, the static fields will reset their value every time an object is created.
public class StaticExample {
static int myStaticField;
public StaticExample(){
myStaticField = 10;
}
}
public class Solution {
public static void main(String[] args) {
StaticExample obj1 = new StaticExample();
StaticExample.myStaticField+= 80;
// this will print 90
System.out.println(StaticExample.myStaticField);
// creating new object will reset the static field
StaticExample obj2 = new StaticExample();
// this will print 10
System.out.println(StaticExample.myStaticField);
}
}
This is unexpected and unaccepted behavior for a static field. If you now change the initialization step from a constructor to a static block, you will get the correct values.
public class StaticExample {
static int myStaticField;
static {
myStaticField = 10;
}
}
public class Solution {
public static void main(String[] args) {
StaticExample obj1 = new StaticExample();
StaticExample.myStaticField+= 80;
// this will print 90
System.out.println(StaticExample.myStaticField);
// creating new object will NOT reset the static field
StaticExample obj2 = new StaticExample();
// this will print 90
System.out.println(StaticExample.myStaticField);
}
}
I have started learning Java language for Android Application developement.
As per my understanding based on static class, we cannot instantiate object of static class.
But why instantiation of static nested class object is allowed in following situaltion?
class EnclosingClass
{
//...
class static StaticInnerClass
{
//...
}
}
Why we can create object of inner class if it is marked as static?
EnclosingClass.StaticInnerClass s = new EnclosingClass.StaticInnerClass()
As per my understanding based on static class, we cannot instantiate object of static class.
Your understanding of the meaning of "static class" is incorrect. Basically a "static class" in Java is a nested class which doesn't have an implicit reference to an instance of the containing class. See section 8.5.1 of the JLS for more information, in particular:
The static keyword may modify the declaration of a member type C within the body of a non-inner class or interface T. Its effect is to declare that C is not an inner class. Just as a static method of T has no current instance of T in its body, C also has no current instance of T, nor does it have any lexically enclosing instances.
Perhaps you were thinking of static classes in C#, which are completely different?
Why we can create object of inner class if it is marked as static?
You may need to use a nested class in a static context, for example:
public class Test {
public static void main(String args[]) {
InnerClass innerClass = new InnerClass();
}
class InnerClass {
}
}
In this case, when you try to instantiate the innerClass you get the error:
No enclosing instance of type Test is accessible. Must qualify the
allocation with an enclosing instance of type Test (e.g. x.new A()
where x is an instance of Test).
To avoid this, you could instantiate an object of type Test and create an instance of innerClass from it:
Test test = new Test();
InnerClass innerClass = test.new InnerClass();
or better, declare also the innerClass as static and instantiate it in a static context:
public class Test {
public static void main(String args[]) {
InnerClass innerClass = new InnerClass();
}
static class InnerClass {
}
}
check it, maybe it can help you
Nested Classes
Why are you not able to declare a class as static in Java?
Only nested classes can be static. By doing so you can use the nested class without having an instance of the outer class.
class OuterClass {
public static class StaticNestedClass {
}
public class InnerClass {
}
public InnerClass getAnInnerClass() {
return new InnerClass();
}
//This method doesn't work
public static InnerClass getAnInnerClassStatically() {
return new InnerClass();
}
}
class OtherClass {
//Use of a static nested class:
private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();
//Doesn't work
private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
//Use of an inner class:
private OuterClass outerclass= new OuterClass();
private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}
Sources :
Oracle tutorial on nested classes
On the same topic :
Java: Static vs non static inner class
Java inner class and static nested class
Top level classes are static by default. Inner classes are non-static by default. You can change the default for inner classes by explicitly marking them static. Top level classes, by virtue of being top-level, cannot have non-static semantics because there can be no parent class to refer to. Therefore, there is no way to change the default for top-level classes.
So, I'm coming late to the party, but here's my two cents - philosophically adding to Colin Hebert's answer.
At a high level your question deals with the difference between objects and types. While there are many cars (objects), there is only one Car class (type). Declaring something as static means that you are operating in the "type" space. There is only one. The top-level class keyword already defines a type in the "type" space. As a result "public static class Car" is redundant.
Class with private constructor is static.
Declare your class like this:
public class eOAuth {
private eOAuth(){}
public final static int ECodeOauthInvalidGrant = 0x1;
public final static int ECodeOauthUnknown = 0x10;
public static GetSomeStuff(){}
}
and you can used without initialization:
if (value == eOAuth.ECodeOauthInvalidGrant)
eOAuth.GetSomeStuff();
...
You can create a utility class (which cannot have instances created) by declaring an enum type with no instances. i.e. you are specificly declaring that there are no instances.
public enum MyUtilities {;
public static void myMethod();
}
Sure they can, but only inner nested classes. There, it means that instances of the nested class do not require an enclosing instance of the outer class.
But for top-level classes, the language designers couldn't think of anything useful to do with the keyword, so it's not allowed.
public class Outer {
public static class Inner {}
}
... it can be declared static - as long as it is a member class.
From the JLS:
Member classes may be static, in which case they have no access to the instance variables of the surrounding class; or they may be inner classes (§8.1.3).
and here:
The static keyword may modify the declaration of a member type C within the body of a non-inner class T. Its effect is to declare that C is not an inner class. Just as a static method of T has no current instance of T in its body, C also has no current instance of T, nor does it have any lexically enclosing instances.
A static keyword wouldn't make any sense for a top level class, just because a top level class has no enclosing type.
As explained above, a Class cannot be static unless it's a member of another Class.
If you're looking to design a class "of which there cannot be multiple instances", you may want to look into the "Singleton" design pattern.
Beginner Singleton info here.
Caveat:
If you are thinking of using the
singleton pattern, resist with all
your might. It is one of the easiest
DesignPatterns to understand, probably
the most popular, and definitely the
most abused.
(source: JavaRanch as linked above)
In addition to how Java defines static inner classes, there is another definition of static classes as per the C# world [1]. A static class is one that has only static methods (functions) and it is meant to support procedural programming. Such classes aren't really classes in that the user of the class is only interested in the helper functions and not in creating instances of the class. While static classes are supported in C#, no such direct support exists in Java. You can however use enums to mimic C# static classes in Java so that a user can never create instances of a given class (even using reflection) [2]:
public enum StaticClass2 {
// Empty enum trick to avoid instance creation
; // this semi-colon is important
public static boolean isEmpty(final String s) {
return s == null || s.isEmpty();
}
}
Everything we code in java goes into a class. Whenever we run a class JVM instantiates an object. JVM can create a number of objects, by definition Static means you have the same set of copy to all objects.
So, if Java would have allowed the top class to be static whenever you run a program it creates an Object and keeps overriding on to the same Memory Location.
If You are just replacing the object every time you run it whats the point of creating it?
So that is the reason Java got rid of the static for top-Level Class.
There might be more concrete reasons but this made much logical sense to me.
The only classes that can be static are inner classes. The following code works just fine:
public class whatever {
static class innerclass {
}
}
The point of static inner classes is that they don't have a reference to the outer class object.
I think this is possible as easy as drink a glass of coffee!.
Just take a look at this.
We do not use static keyword explicitly while defining class.
public class StaticClass {
static private int me = 3;
public static void printHelloWorld() {
System.out.println("Hello World");
}
public static void main(String[] args) {
StaticClass.printHelloWorld();
System.out.println(StaticClass.me);
}
}
Is not that a definition of static class?
We just use a function binded to just a class.
Be careful that in this case we can use another class in that nested.
Look at this:
class StaticClass1 {
public static int yum = 4;
static void printHowAreYou() {
System.out.println("How are you?");
}
}
public class StaticClass {
static int me = 3;
public static void printHelloWorld() {
System.out.println("Hello World");
StaticClass1.printHowAreYou();
System.out.println(StaticClass1.yum);
}
public static void main(String[] args) {
StaticClass.printHelloWorld();
System.out.println(StaticClass.me);
}
}
One can look at PlatformUI in Eclipse for a class with static methods and private constructor with itself being final.
public final class <class name>
{
//static constants
//static memebers
}
if the benefit of using a static-class was not to instantiate an object and using a method then just declare the class as public and this method as static.