Class initialization trouble: static variables are null when accessed [duplicate] - java

I'm running into a problem when I compile my code. When I compile my code foo2.var returns null in class foo and I can't seem to figure out why. Is there something wrong in how I'm doing the static initialization in the foo2 class to cause foo2.var to be null in the foo class?
Any help is appreciated.
public class foo extends bar {
public final static String blah = foo2.var;
...
}
public abstract class bar {
...
}
public class foo2 extends bar {
public final static String var;
static {
var = "newstring";
}
...
}
Null pointer error on the foo2.var line in this example.

Accessing a static field (whose value is not a compile-time-constant expression) will trigger initialization of the class declaring that field, during which which the static initializers are executed. However, initialization is only guaranteed to have completed by the time the field is read if there is no cyclic dependency among initializers.
For instance, if you run the program
class Bar {
static final long bar;
static {
System.out.println("Assigning bar");
bar = Foo.foo;
}
}
class Foo extends Bar {
static final long foo;
static {
System.out.println("Assigning foo");
foo = 1;
}
}
public class Test {
public static void main(String[] args) {
new Foo();
System.out.println(Bar.bar);
}
}
you get the following output:
Assigning bar
Assigning foo
0
1
because to create a new instance of Foo, Foo.class is initialized, which first initializes its super class Bar.class, which reads the field of Foo.class, but Foo.class is already being initialized. The Java Language Specification mandates in section 12.4.2, step 3, that such a recursive initialization completes immediately, i.e. the caller will see the class in a partially initialized state. That is, Foo.foo is unassigned at the time it is read, and therefore still contains the default value of 0. That value is assigned to Bar.bar, completing initialization of Bar.class. Then, initialization of Foo.class is resumed by running the initializer, which sets Foo.foo to 1.
Practically speaking, you might wish to review the dependencies of your classes and structure your program such that there are no cyclic dependencies among initializers.

You have not specified a type for var try public final static String VAR;
and then why not just
public class foo2 extends bar {
public final static String var = "newstring";

var doesn't have a type. Also constants in Java are uppercase by convention. Make it:
public class Foo2 {
public final static String VAR;
static {
VAR = "newstring";
}
...
}

You are missing a type for var, change that line to the following:
public final static String VAR;

Specify var type.
Also, by coding convention class names should be written in CamelCase and constants, UNDERSCORED_CAPS
public class Foo2 {
public final static VAR = "newstring"; // why not?
...
}
Also, you may shadow foo2 class by some variable. Check your imports. Because class static field reference cannot produce NPE!

Related

Is there any annotation to warn that subclasses shouldn't hide a static method in Java

I have a class which contains a public static method in Java. Is there any annotation in java to warn the subclasses not to use same method signature(and thereby hide the superclass method). Any other workarounds would also be fine.
Just make the superclass method final:
class Foo {
public static final void go() {}
}
class Bar extends Foo {
public static void go() {}; // Error
}
Ideone Example
you dont need such annotations because what you a trying to do in not going to compile...
in java you just can not override static method
as #thomas suggested(+1 dafuer), you can play with the visibility of the static method
example:
public class Calculator {
static int add(int a, int b) {
System.out.println("a+b= " + (a + b));
return a + b;
}
public static void main(String[] args) {
}
}
and then
public class ScientificCalculator extends Calculator {
public int add(int a, int b) {
System.out.println("11111");
return a + b;
}
}
I don't know of any such annotation to flag the declaration of the method. You could, however, approach this from the opposite direction. Instead of focusing on the method declaration, you could look at uses of it. The -Xlint:all will warn if any uses could be a problem. A static method with an identical signature to a static method in its superclass will only cause problems when that method is referenced from an instance instead of statically. Consider this example:
public class Foo {
public static String getFoo(){
return "foo";
}
}
public class Bar extends Foo {
public static void main(String[] args){
Bar bar = new Bar();
String s = bar.getFoo(); // Actually calls Foo.getFoo()
System.out.println(s); // Prints "foo"
}
}
In the code above, we reference the static getFoo() method from Foo through an instance of Bar. The bar.getFoo() line actually calls the static method from Foo. Now suppose we add a static method with an identical signature to Bar:
public class Bar extends Foo {
public static String getFoo(){
return "bar";
}
public static void main(String[] args){
Bar bar = new Bar();
String s = bar.getFoo(); // Actually calls Bar.getFoo()
System.out.println(s); // Prints "bar"
}
}
This hides the Foo.getFoo() method from Bar and now the Bar.getFoo() method is invoked instead. In a real context, this would almost certainly break Bar. If you compile with the -Xlint:all option, then you'd get this message:
warning: [static] static method should be qualified by type name, Foo, instead of by an expression
You'd notice this when you compile the first version of Bar and you could fix it to String s = Foo.getFoo() right away. Later when getFoo is also added to Bar, the original code will still work because it explicitly references the method in Foo. If you always explicitly call static methods by referencing the class in which they are declared, then the only problem with having an identical method in a subclass is that it's not exactly a best practice. Maybe there is a way to flag the declaration, too, but I'd focus on making sure that the static method is used properly.

What are the differences between instance final fields from Java and readonly instance fields from C#?

In general - equivalent of final field in Java is the readonly field in C#. But the more I read about C# the more I see that there are some differences in details.
I've found myself two differences:
Fields marked as readonly assigned as part of definition can be reasigned in constructor
In Java it is not possible to do that with final fields. Examples:
Example - C Sharp
public class Foo
{
public readonly int a = 1;
public Foo()
{
a = 2;
}
}
and now
Foo f = new Foo();
Console.WriteLine(f.a);
will give us 2 as an output
(side question - is this behavior can be actualy used for something useful? As far as I know I cannot assign value to base class' readonly field in dervied class)
Example - Java
class Foo {
private final int i = 3;
public Foo() {
// compilation error
// i = 2;
}
}
Orders of initalization of readonly and final fields in class hierarchy are different in both languages
In Java it will go from base class to dervied.
In C# it will go from derived class to base.
Example - C Sharp
Based on article Eric Lippert: Why Do Initializers Run In The Opposite Order As Constructors? Part One:
public class Print
{
public Print(string text)
{
Console.WriteLine(text);
}
}
public class Base
{
private readonly Print #base = new Print("Base class");
}
public class Derived : Base
{
private readonly Print derived = new Print("Derived class");
}
In case of calling new Derived() we will see:
Derived class
Base class
As far as I understood - this order of initalization guarantees that readonly fields are always initalized before usage. In case of following code (based on second part of Eric's article - Why Do Initializers Run In The Opposite Order As Constructors? Part Two):
public class Foo
{
}
public class Base
{
public Base()
{
if (this is Derived)
{
((Derived)this).danger();
}
}
}
public class Derived : Base
{
private readonly Foo derived = new Foo();
public void danger()
{
Console.WriteLine("access: {0}", derived.GetHashCode());
}
}
Calling new Derived() is safe.
Example - Java
Similar code in Java:
class Print {
public Print(String text) {
System.out.println(text);
}
}
class Base {
private final Print base = new Print("Base class");
}
class Derived extends Base {
private final Print derived = new Print("Derived class");
}
Call new Derived() will result with:
Base class
Derived class
So in case of following code:
class Base {
public Base() {
if (this instanceof Derived) {
((Derived)this).danger();
}
}
}
class Derived extends Base {
private final Foo field = new Foo();
public void danger()
{
System.out.println("access: " + field.hashCode());
}
}
The call new Derived() will result with NullPointerException
Question
My question is: Are there other differences (even small ones) between Java's final fields and readonly fields in C# ? To make question more clear - I have in mind only final instance fields in Java (so no static finals, no final variables, no other final "thigs")

setting a static variable in java

I am new to java hence probably a very noob question:
I have a class
public class Foo{
private static String foo;
private String bar;
public Foo(String bar){
this.bar = bar;
}
}
Now before I instantiate any object for class Foo, I want to set that static variable foo.
which will be used in the class..
How do i do this?
Also, please correct my understanding. value of foo will be same across all the objects, hence it does make sense to declare it as static ? right?
public class Foo{
private static String foo = "initial value";
private String bar;
public Foo(String bar){
this.bar = bar;
}
}
Since the value will be the same across all objects, static is the right thing to use. If the value is not only static but also never changing, then you should do this instead:
public class Foo{
private static final String FOO = "initial value";
private String bar;
public Foo(String bar){
this.bar = bar;
}
}
Notice how the capitalization changed there? That's the java convention. "Constants" are NAMED_LIKE_THIS.
foo will be shared among all instances of Foo
To initialize it:
Option A
private static String foo = "static variable";
Option B
private static String foo;
static {
foo = "static variable";
}
Option B is seldom used, mostly when there are some inter-dependencies between static variables or potential exceptions.
In either case, static init will happen when the class is loaded.
As stated by the other answers, you should set your initial value like so:
private static String foo = "initial value";
Additionally, if you want to access this variable from anywhere, you need to reference it in a static context, like so:
Foo.foo
where Foo is the class name, and foo is the variable name.
This is actually very useful in understanding the concept of static variables. Rather than referencing foo as a member of some instance of the Foo class, you are referencing foo as a member of the class itself. So, for all instances of Foo, the value of foo will be the same because it is owned by the class and not the instance.
Inside the Foo class, you can get away with just calling foo without qualifying it with a class name.

Global variables and constructor(Java)

When are variables at the top of the class initialized in comparison to the constructor?
Sorry, this is what I meant:
public class aClass {
private int num;
public aClass {...}
Default values (null for object fields, 0 etc. for primitive fields`) are technically never explicitly assigned as far as the emitted bytecode is concerned. (This is done "internally" during object instantiation, before any initializer/constructor code runs.)
Explicit initializer code for instance fields is "copied" at the start of every constructor, after a superclass constructor call (if there is any) in the class by the compiler. The code sample:
class Foo {
int bar = 123;
public Foo() {
// ...
}
public Foo(int bar) {
this.bar = bar;
// ...
}
}
is compiled into bytecode equivalent to:
class Foo {
int bar;
public Foo() {
this.bar = 123;
// ...
}
public Foo(int bar) {
this.bar = 123;
this.bar = bar;
// ...
}
}
Same goes for initializer blocks. This means these variables get initialised before any normal constructor code executes.
Members defined with values are initialized in the constructor, just like any other members. But it's not exactly the constructor you wrote; Java changes each constructor behind the scenes by inserting member initializers and initializer blocks in the beginning of it. You could view it as the members getting initialized just before the constructor, if you want to view it temporally.
Effectively, you can consider them initialized before your constructor gets called. So if you have:
class Dog {
private String voice = "woof";
public Dog() {
System.out.println(voice);
}
}
You'll get "woof" printed to the console successfully, rather than null.

Is it true that the assigned final object field may still be null inside a constructor?

Is it true that the assigned final object field may still be null inside a constructor?
class MyClass {
private final Object obj = new Object();
public MyClass() {
System.out.println(obj); // may print null?
}
}
if yes, isn't this a bug?
As discussed by other answers, no, that can not happen. With an assigned final static field, however, it can.
class MyClass {
private static MyClass myClass = new MyClass();
private static final Object obj = new Object();
public MyClass() {
System.out.println(obj); // will print null once
}
}
This is not possible as the as all initializers run before the constructor is invoked.
Variable initializers like you have private final Object obj = new Object(); run before the constructor is invoked. This is also true of initialisation blocks static or otherwise.
One thing to watch out for when using initializers is that initializers can't make forward references When you write an initializer, you cannot refer to any instance variables declared textually after the variable being initialized.
The initializer Object obj = new Object(); will run before the code inside the constructor, so obj cannot be null.
Note that this would not compile if you did not initialize obj anywhere.
Works for me:
$ cat MyClass.java
class MyClass {
private final Object obj = new Object();
public MyClass() {
System.out.println(obj); // may print null?
}
public static void main(String[] args) { new MyClass(); }
}
$javac MyClass.java; java MyClass
java.lang.Object#19908ca1
All field initializers are copied by the compiler into the begining of all constructors.
However, under the Java 5 memory model, if you let the this reference 'escape' before the end of the constructor, other threads can see uninitialized values of final fields (so could see null in this case).
With a simple example like yours, nothing bad can happen. However, it is possible for a final field to be visible as uninitialised if you use questionable practices such as calling an overridable method in your constructor.
For example, the following program prints "My favourite colour is null", even though it references the final variable favouriteColour, which is set to "blue" in the constructor.
abstract class SuperClass {
final String favouriteColour;
SuperClass() {
announceFavouriteColour();
favouriteColour = "blue";
}
abstract void announceFavouriteColour();
}
public class FinalTest extends SuperClass {
void announceFavouriteColour() {
System.out.println("My favourite colour is " + favouriteColour);
}
public static void main(String[] args) {
new FinalTest();
}
}

Categories