Field can't be static? - java

There is error with this code
public class DoIt {
public static void main(String[] args) {
final class Apple {
public static String place = "doIt";
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println(Constants.place);
}
});
thread.start();
}
}
Error- The field name cannot be declared static in a non-static inner type, unless initialized with a constant expression

The problem is that the field is non-final: only final fields are allowed to be static in the context of non-static inner classes:
final class Apple {
// This should compile
public static final String place = "doIt";
}

JLS 8.1.3
Inner classes may not declare static members, unless they are constant
variables (§4.12.4), or a compile-time error occurs.
final class Apple {
public static final String place = "doIt"; // This is good
}
Inner classes are instance classes. The point of using a static member is to call it directly without having to instantiate. So it wouldn't make much sense to allow static members inside an inner class. However, you can declare them as static-
static final class Apple {
public static String place = "doIt";
}

final class Apple { {
// you can't define non final field inside the final class
// you have to use final with static
}
you can use
public final static String place = "doIt";

According to the Java tutorials,
A local class can have static members provided that they are constant variables.
So you would have to declare it final:
public static void main(String[] args) {
final class Apple {
public static final String place = "doIt";
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("");
}
});
thread.start();
}

Before i reason out the error terminology is as follows
Terminology: Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes(more specifically local inner class).
Now in your case you have local inner class. According to the docs Because an inner class is associated with an instance, it cannot define any static members itself.
Objects that are instances of an inner class exist within an instance of the outer class and static members are loaded when classes are loaded whereas in your case you cannot access Apple class at the time of class loading to load place variable.
Also A local class can have static members provided that they are constant variables.
so you can do public static final String place = "doIt";

Related

Declaring a static variable in a non-static class in Java

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);
}
}

Static Inner class's non static fields real time utility and code syntax

What is the real time utility of non static fields inside static inner class?
Also, how instance creation of static inner class works :
class Outer {
static class Inner {
public final String text = "Inner";
}
}
public class A {
public static void main(String[] args) {
System.out.println(new Outer.Inner().text);
}
}
Just consider static inner class as normal class (just placed inside class instead package) and consider non-static inner class something like generic, based on instance of outer class.

Behavior of static blocks with inheritance

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

java private access modifier can be accessed out side of the class?

Why java compiler is not restricting from accessing a private attribute from other class?
I have inner class which has a attribute 'a' with modifier 'private'. I can able to access this variable with its instance variable out side the class. see the code below.
package com.test;
public class Test {
public Test() {
}
public static void main(String[] args) {
new Test().execute(); // test method
}
public void execute() {
InnerClass innerClassInstance = new InnerClass();
// accessing private member from other class instance, HOW?
System.out.println(innerClassInstance.a);
InnerStaticClass innerStaticClassInstance = new InnerStaticClass();
// accessing private member from other class instance, HOW?
System.out.println(innerStaticClassInstance.a);
}
private final class InnerClass {
private int a; // accessible only in InnerClass??
}
private final static class InnerStaticClass {
private int a; // accessible only in InnerClass??
}
}
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Sorry, I misread the question.
Looks at JLS http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.1
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
So, a field in inner-class (which is obviously inside class body) can be accessed by outer class even if it's private.
See the Java language specification:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
your Inner class is a member of your Test class so, Test class can access private member of Inner class too.
Try like this it will give compile error
public class Test {
public Test() {
}
public static void main(String[] args) {
new Test().execute(); // test method
}
public void execute() {
InnerClass innerClassInstance = new InnerClass();
// accessing private member from other class instance, HOW?
System.out.println(innerClassInstance.a);
InnerStaticClass innerStaticClassInstance = new InnerStaticClass();
// accessing private member from other class instance, HOW?
System.out.println(innerStaticClassInstance.a);
}
}
class InnerClass {
private int a; // accessible only in InnerClass??
}
final class InnerStaticClass {
private int a; // accessible only in InnerClass??
}
These nested classes are meant for that .When you have private
members in a class ,we write nested class to do unit testing.

Can a Static Nested Class be Instantiated Multiple Times?

Given what I know of every other type of static feature of programming––I would think the answer is 'no'. However, seeing statements like OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass(); makes me wonder.
Yes, there is nothing in the semantics of a static nested type that would stop you from doing that. This snippet runs fine.
public class MultipleNested {
static class Nested {
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Nested();
}
}
}
See also
public static interface Map.Entry<K,V>
public static class AbstractMap.SimpleEntry<K,V>
Probably the most well-known nested type. Obviously instantiated multiple times.
Now, of course the nested type can do its own instance control (e.g. private constructors, singleton pattern, etc) but that has nothing to do with the fact that it's a nested type. Also, if the nested type is a static enum, of course you can't instantiate it at all.
But in general, yes, a static nested type can be instantiated multiple times.
Note that technically, a static nested type is not an "inner" type.
JLS 8.1.3 Inner Classes and Enclosing Instances
An inner class is a nested class that is not explicitly or implicitly declared static.
That is, according to JLS terminology, an inner class is one that isn't static. If it's static, then it's just a nested type.
So what does static mean?
static simply means that the nested type does not need an instance of the enclosing type to be instantiated.
See also
Java inner class and static nested class
Java: Static vs non static inner class
#polygenelubricants :
But in general, yes, a static nested
type can be instantiated multiple
times.
Just to be sure 100% of that I extended your snippet:
public class MultipleInner {
static class Inner {
private int state;
public int getState() { return state; }
public void setState(int state) { this.state = state; }
}
public static void main(String[] args) {
List<Inner> inners = new ArrayList<Inner>();
for (int i = 0; i < 100; i++) {
Inner inner = new Inner();
inner.setState(i);
inners.add(inner);
}
for (Inner inner : inners) {
System.out.println(inner.getState());
}
}
}
And of course the result is:
0
1
2
3
.
.
.
97
98
99
It is legal. The fact that the inner class is static gives you a benefit here; its instances are not bound to any instance of the containing class, so they can be freely instantiated (as long as the access qualifier allows it).
The price, however, is that the inner class can't use non static members/methods of the containing class.
Yeah you can make instances of it as many times as you want.
Maybe the reason why you see that, is because the programme thought about storing a reference somewhere. Though i agree with you seems strange :S
Inner class can use non static members/methods of containing class. It can use them only through an object reference of the enclosing class-
public class MultipleInner {
private int outerstate =10;
static class Inner {
private int state;
public int getState() { return state; }
public void setState(int state) { this.state = state; }
}
public static void main(String[] args) {
Inner inner = new Inner();
inner.setState(new MultipleInner().outerstate);
System.out.println(inner.getState());
}
}
So, inner class doesn't have to pay the price of not being able to access the non static members of the enclosing class.
Static nested classes are indeed instanced - they are, as said, top-level classes which live in the namespace of the 'outer' class, and obey static semantics respecting references to the 'outer' class. This code sample demonstrates :
public class OuterClass {
String outerStr = "this is the outer class!!" ;
public static class StaticNestedClass {
String innerStr = "default / first instance" ;
}
public static void main(String[] args) {
OuterClass.StaticNestedClass nestedObject1 = new OuterClass.StaticNestedClass();
OuterClass.StaticNestedClass nestedObject2 = new OuterClass.StaticNestedClass();
nestedObject2.innerStr = "second instance" ;
System.out.println(nestedObject1.innerStr) ;
System.out.println(nestedObject2.innerStr) ;
}
}
output:
default / first instance
second instance

Categories