I am new to java. I am currently reading some articles about static variables. When I am trying to implement my learnings, I encountered a problem about static variables. Here is the first code sample.
public class Human {
// in Human.java
public static int population = 0;
public static void main(String[] argv) {
System.out.println(population);
}
}
This code works fine and the outcome is 0.
But for the following code, I wasn't allow to compile it.
public class Human {
// in Human.java
public class Charlie extends Human {
public static int number = 0;
}
public static void main(String[] argv) {
System.out.println(new Human().new Charlie().number);
}
}
An error occurred: The field number cannot be declared static in a non-static inner type, unless initialized with a constant expression
I am confused with this situation. For the first code sample, my Human class is non-static and I was allowed to declare a static variable inside it. How come I can't do the same for my second code sample.
Any help would be appreciated. Thanks. :)
Try with public static final int number = 0; because Java does not let you define non-final static fields inside function-local inner classes. Only top-level classes and static nested classes are allowed to have non-final static fields.
From the JLS section 8.1.3:
Inner classes may not declare static members, unless they are constant variables (§4.12.4), or a compile-time error occurs.
Other way to make inner class static and access it
public class Human {
// in Human.java
public static class Charlie extends Human {
public static int number = 0;
}
public static void main(String[] argv) {
System.out.println(new Human.Charlie().number);
}
}
Related
I want to initialize Final.value in Main method.
Is it possible to initialize static final constant in other class than
in its deceleration class?
public class Main {
public static void main(String[] args) {
//I want to initialize Final.value in Main method.
}
}
class Final {
//here is the static final variable which can be assigned vai a static block
//but how do I initialize it in the main method if I don't use the static block?
static final int value;
}
You cannot. Your perception might be that main happens before everything else, so it is safe to initialise things there, but that is incorrect.
Consider the following code.
class Scratch
{
static
{
System.out.println(Foo.i);
}
public static void main(String[] args)
{
Foo.i = 100;
}
}
class Foo
{
static int i;
}
It does not print 100. It prints 0 because there are other things which happen before main.
Making the field final does not change that fact.
You have two options for static initialization. In a static initializer block, like you showed, or in-line:
static final int value = 421
Java prevents you from doing what you want to do for a good reason: because it is likely to lead to bugs.
public class A{
public static void main(String[] args){
static final int MAX_VALUE = 100; //COMPILE TIME ERROR
System.out.println("MAX_VALUE");
}
}
Why static final int MAX_VALUE=100; gives compile time error, it gives the error as "illegal modifier for parameter MAX_VALUE;only final is permitted "
You cannot declare static variable inside methods.
Static variables belong to the class; variables declared inside a method are local variables and belong to that method.
Static variables belong to the class.Not methods
The variables declared inside a method are local variables and belong to that method.
So it becomes
final int MAX_VALUE = 100;
Prefer to read : Docs on Understanding Instance and Class Members
The keyword static cannot be used inside methods. This would be valid code:
public class A{
static final int MAX_VALUE = 100; // This line can't go in a method.
public static void main(String[] args){
System.out.println("MAX_VALUE: "+MAX_VALUE);
}
}
A local variable can not be static. You can either create a final local variable, or a final static class variable (which are actually constants, btw.), but not a local static variable:
public class A{
static final int CLASS_CONST = 42;
public static void main(String[] args){
final int LOCAL_CONST = 43;
...
}
}
You can't delcare static things inside a method. Move it up a line.
Change
public class A{
public static void main(String[] args){
static final int MAX_VALUE = 100; //COMPILE TIME ERROR
System.out.println("MAX_VALUE");
}
}
To
public class A{
static final int MAX_VALUE = 100; //NO ERROR YAY!!
public static void main(String[] args){
System.out.println("MAX_VALUE");
}
}
you can't create static final in a method, you must create it outside the method:
public class A {
static final int MAX_VALUE = 100;
public static void main(String[] args){
System.out.println("MAX_VALUE");
}
}
static variables are class level variables ,you can't declare them at method.
According Docs
Sometimes, you want to have variables that are common to all objects.
This is accomplished with the static modifier. Fields that have the static
modifier in their declaration are called static fields or class variables.
They are associated with the class, rather than with any object
Others already pointed out that static members belong to the class instead of a specific instance. So you don't have to create a class instance to use a static member, rather you can call SomeClass.SOME_STATIC_MEMBER directly.
You cannot call any other member of a class that is not static without instantiating that class. Meaning if you have-
public class SomeClass {
public int add (int x, int y){
return x + y;
}
}
For you to use add method of SomeClass above, you have to instantiate first-
SomeClass someClass = new SomeClass();
int sum = someClass.add(5, 10);
So, there is no point of allowing us to declare static members in a non-static method as for us to use that method, we have to instatiate the class where that method belongs to.
you should declare this constant in the class A, not in the main() method
public class A{
static final int MAX_VALUE = 100; //COMPILE TIME ERROR
public static void main(String[] args){
System.out.println("MAX_VALUE");
}
}
It is said that non-static variables cannot be used in a static method. But public static void main does. How is that?
No, it doesn't.
public class A {
int a = 2;
public static void main(String[] args) {
System.out.println(a); // won't compile!!
}
}
but
public class A {
static int a = 2;
public static void main(String[] args) {
System.out.println(a); // this works!
}
}
or if you instantiate A
public class A {
int a = 2;
public static void main(String[] args) {
A myA = new A();
System.out.println(myA.a); // this works too!
}
}
Also
public class A {
public static void main(String[] args) {
int a = 2;
System.out.println(a); // this works too!
}
}
will work, since a is a local variable here, and not an instance variable. A method local variable is always reachable during the execution of the method, regardless of if the method is static or not.
Yes, the main method may access non-static variables, but only indirectly through actual instances.
Example:
public class Main {
public static void main(String[] args) {
Example ex = new Example();
ex.variable = 5;
}
}
class Example {
public int variable;
}
What people mean when they say "non-static variables cannot be used in a static method" is that non-static members of the same class can't be directly accessed (as shown in Keppils answer for instance).
Related question:
Accessing non-static members through the main method in Java
Update:
When talking about non-static variables one implicitly means member variables. (Since local variables can't possible have a static modifier anyway.)
In the code
public class A {
public static void main(String[] args) {
int a = 2;
System.out.println(a); // this works!
}
}
you're declaring a local variable (which typically is not referred to as non-static even though it doesn't have a static modifier).
The main method does not have access to non-static members either.
final public class Demo
{
private String instanceVariable;
private static String staticVariable;
public String instanceMethod()
{
return "instance";
}
public static String staticMethod()
{
return "static";
}
public static void main(String[] args)
{
System.out.println(staticVariable); // ok
System.out.println(Demo.staticMethod()); // ok
System.out.println(new Demo().instanceMethod()); // ok
System.out.println(new Demo().instanceVariable); // ok
System.out.println(Demo.instanceMethod()); // wrong
System.out.println(instanceVariable); // wrong
}
}
This is because by default when you call a method or variable it is really accessing the this.method() or this.variable. But in the main() method or any other static method(), no "this" objects has yet been created.
In this sense, the static method is not a part of the object instance of the class that contains it. This is the idea behind utility classes.
To call any non-static method or variable in a static context, you need to first construct the object with a constructor or a factory like your would anywhere outside of the class.
More depth:
Basically it's a flaw in the design of Java IMO which allows static members (methods and fields) to be referenced as if they were instance members. This can be very confusing in code like this:
Thread newThread = new Thread(runnable);
newThread.start();
newThread.sleep(1000);
That looks like it's sending the new thread to sleep, but it actually compiles down into code like this:
Thread newThread = new Thread(runnable);
newThread.start();
Thread.sleep(1000);
because sleep is a static method which only ever makes the current thread sleep.
Indeed, the variable isn't even checked for non-nullity (any more; it used to be, I believe):
Thread t = null;
t.sleep(1000);
Some IDEs can be configured to issue a warning or error for code like this - you shouldn't do it, as it hurts readability. (This is one of the flaws which was corrected by C#...)
**Here you can see table that clear the access of static and non-static data members in static and non-static methods. **
You can create non-static references in static methods like :
static void method() {
A a = new A();
}
Same thing we do in case of public static void main(String[] args) method
public class XYZ
{
int i=0;
public static void increament()
{
i++;
}
}
public class M
{
public static void main(String[] args)
{
XYZ o1=new XYZ();
XYZ o2=new XYZ();
o1.increament();
XYZ.increament(); //system wont be able to know i belongs to which object
//as its increament method(static method)can be called using class name system
//will be confused changes belongs to which object.
}
}
I have a source-code generator that risks generating the following type of code (just an example):
public class Outer {
public static final Object Inner = new Object();
public static class Inner {
public static final Object Help = new Object();
}
public static void main(String[] args) {
System.out.println(Outer.Inner.Help);
// ^^^^ Cannot access Help
}
}
In the above example, Inner is ambiguously defined inside of Outer. Outer.Inner can be both a nested class, and a static member. It seems as though both javac and Eclipse compilers cannot dereference Outer.Inner.Help. How can I access Help?
Remember, the above code is generated, so renaming things is not a (simple) option.
The following works for me (with a warning about accessing static members in a non-static way):
public static void main(String[] args) {
System.out.println(((Inner)null).Help);
}
How about
public static void main(String[] args) {
System.out.println(new Inner().Help);
}
I am trying to use static blocks like this:
I have a base class called Base.java
public class Base {
static public int myVar;
}
And a derived class Derived.java:
public class Derived extends Base {
static
{
Base.myVar = 10;
}
}
My main function is like this:
public static void main(String[] args) {
System.out.println(Derived.myVar);
System.out.println(Base.myVar);
}
This prints the out put as 0 0 where as I expected 10 0. Can somebody explain this behavior? Also, if I want my derived classes to set the values for a static variable how can I achieve that?
As I understand. You don't call any Derived properties (myVar belongs to Base, not to Derived). And java is not running static block from Derived. If you add some static field to Derived and access it, then java executes all static blocks.
class Base {
static public int myVar;
}
class Derived extends Base {
static public int myVar2;
static
{
Base.myVar = 10;
}
}
public class Main {
public static void main( String[] args ) throws Exception {
System.out.println(Derived.myVar2);
System.out.println(Base.myVar);
}
}
From java specification, when class is initialized (and static block got executed):
12.4.1 When Initialization Occurs A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
• T is a class and an instance of T is created.
• T is a class and a static method declared by T is invoked.
• A static field declared by T is assigned.
• A static field declared by T is used and the field is not a constant variable (§4.12.4).
• T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
Static initializer-blocks aren't run until the class is initialized. See Java Language Specification paragraphs 8.7 (Static initializers) and 12.4.1 (When initialization occurs):
A static initializer declared in a class is executed when the class is
initialized (§12.4.2). Together with any field initializers for class
variables (§8.3.2), static initializers may be used to initialize the
class variables of the class.
Here's a similar example straight out of JLS 12.4.1:
class Super {
static int taxi = 1729;
}
class Sub extends Super {
static { System.out.print("Sub "); }
}
class Test {
public static void main(String[] args) {
System.out.println(Sub.taxi);
}
}
This program prints only:
1729
because the class Sub is never initialized; the reference to Sub.taxi
is a reference to a field actually declared in class Super and does
not trigger initialization of the class Sub.
There is a single copy of myVar and both parent and child class will share the same.
Untill and unless child class get initilized.
When we do
class Base {
public static int myVar = 0;
static {
System.out.println("Base");
}
}
class Derived extends Base {
static {
System.out.println("Derived");
Base.myVar = 9;
}
}
public class StaticBlock {
public static void main(String[] args) {
System.out.println(Base.myVar);
System.out.println(Derived.myVar);
}
}
The Output will be
Base
0
0
That means derived class's static block not executing..!!
Here is the link to the Java Specification - section 8.7 talks about static initializers. It gives good details about how they should function and the order in which they get called. http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.7