I have this piece of code, and the compiler's returns with NullPointerException where I try to create BtnAct. I've read much about initialization but still haven't come across in what order inner classes are initialized. Can someone help please?
public class BaseClass{
static Myclass myClass;
public static void main(){
myClass = new MyClass;
}
}
class MyClass{
NewClass newClass;
public MyClass(){
newClass = new NewClass();
}
class BtnActn extends AbstractAction {
BtnActn() {
super("Button");
}
#Override
public void actionPerformed(ActionEvent e) {
//blabla
}
}
}
class NewClass{
JButton button;
public NewClass(){
button = new JButton(BaseClass.myClass.new BtnActn()); //NullPointer.ex here
}
}
Here is what happens:
Base class tries to create an instance of MyClass. Please notice that at that time it's not assigned to myClass yet
the new instance of MyClass tries to create an instance of NewClass. Please notice that at that time, it's not assigned to the variable newClass yet
the new instance of NewClass tries to create a new instance of JButton. For that purpose, it first needs to access BaseClass.myClass. Unfortunately, the object BaseClass.myClass is already in memory (it's in the process of being initialized at that time), but it's not assigned to the BaseClass.myClass variable yet. So it makes a NullPointerException.
So you need to separate the initialization of your Button from the initialization of myClass variable in BaseClass.
I've read much about initialization but still haven't come across in what order inner classes are initialized.
Class initialization is about the initialization of a classes static fields and execution of static initializer blocks. However, an inner class in Java is not allowed to have any static fields or static initializers. (See JLS 8.1.3.) Hence (real) class initialization for inner classes is moot. It makes no difference when it happens ... 'cos there is nothing in an inner class to initialize.
The real problem here is that while you have a static field, its actual initialization (to a non-null value) is not done during static initialization. Rather, it would happen when some part of your code explicitly calls BaseClass.main(). However, none of your code does that ... and hence myClass is going to be null when you try to use it.
Again ... I stress ... this is not an issue of how static initialization works, because your code doesn't use static initialization to initialize the field in question.
Related
Conditions to recreate (as far as I can tell):
nested enum references a parent static member
nested class
static member of parent class takes enum as an constructor argument to nested class
enum is referenced by an external class before anything else in the parent class
Run this code online:
https://repl.it/repls/PlushWorthlessNetworking
import java.util.ArrayList;
class Recreate {
private static ArrayList FEATURES = new ArrayList();
public enum Car {
TESLA(FEATURES);
Car(ArrayList l) { }
}
public static class Garage {
final Car car;
Garage(Car car) {
this.car = car;
}
}
public static Garage ONE_CAR_GARAGE = new Garage(Car.TESLA);
}
class Main {
public static void main(String[] args) {
// inclusion of this line causes the next line to NPE
System.out.println(Recreate.Car.TESLA);
System.out.println(Recreate.ONE_CAR_GARAGE.car.toString());
}
}
Here is what is happening:
The main method starts executing
You refer to Recreate.Car.TESLA
The classloader starts to load and initialize enum Car. As noted below, class Recreate is NOT yet loaded or initialized.
The initializer for TESLA refers to FEATURES
This causes class Recreate to be loaded and initialized
As part of static initialization of Recreate, Class Garage is loaded, intialized, and the instance ONE_CAR_GARAGE is created.
The problem here is that at this point, the construction of enum Car is not complete, and Car.TESLA has the value null.
Even though classes may be nested, it is not the case that nested classes are loaded and initialized as part of the outer class initialization. They may look nested in the source but each and every class is independent. Static nested classes are equivalent to top-level classes. Non-static classes are also the same but have the ability to refer to members in the containing class via a hidden reference.
You can see for yourself if you run this in a debugger, put breakpoints in several places, and examine the stack at each breakpoint.
I tested/debugged this in Eclipse with the following code, with breakpoints set where indicated. It's slightly different from your code but shouldn't behave differently:
public class Foo5
{
static class Recreate {
private static ArrayList FEATURES = new ArrayList();
public enum Car {
TESLA(FEATURES);
Car(ArrayList l) {
System.out.println("car"); // *** Breakpoint ***
}
}
public static Garage ONE_CAR_GARAGE = new Garage(Car.TESLA);
public static class Garage {
final Car car;
Garage(Car car) {
this.car = car; // *** Breakpoint ***
}
}
}
public static void main(String[] args) throws Exception {
Recreate.Car car = Recreate.Car.TESLA;
System.out.println(Recreate.Car.TESLA);
System.out.println(Recreate.ONE_CAR_GARAGE.car.toString());
}
}
The first breakpoint you will hit will be the one in the Garage(Car car) constructor. Examining the stack at that point you will see
Foo5$Recreate$Garage.<init>(Foo5$Recreate$Car) line: 23
Foo5$Recreate.<clinit>() line: 17
Foo5$Recreate$Car.<clinit>() line: 12
Foo5.main(String[]) line: 29
So when the Garage constructor is called, it has not yet returned from creating Car. This is dictated by the convoluted dependencies you have created between classes, so the solution is to untangle the dependencies. How you do that will depend on your ultimate goals.
You have a hidden circular dependency that's confusing the JVM. Let's take a look at your code.
class Recreate {
private static ArrayList FEATURES = new ArrayList();
public enum Car {
TESLA(FEATURES);
Car(ArrayList l) { }
}
public static class Garage {
final Car car;
Garage(Car car) {
this.car = car;
}
}
public static Garage ONE_CAR_GARAGE = new Garage(Car.TESLA);
}
We'll also need a few snippets from a page out of the JLS.
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
A static field declared by T is used and the field is not a constant variable (§4.12.4).
12.4.2. Detailed Initialization Procedure
...
Next, execute either the class variable initializers and static initializers of the
class, or the field initializers of the interface, in textual order, as though they
were a single block.
So our static data is being initialized when it's first referenced. Now, your Car.TESLA is implicitly static final, but it's not a constant, as per the definition.
A constant variable is a final variable of primitive type or type String that is initialized with a constant expression
So for our purposes, there are three static non-constant variables in play here: FEATURES, TESLA, and ONE_CAR_GARAGE.
Now, in your working case, you reference Recreate.ONE_CAR_GARAGE. This is a reference to a static field in Recreate, so FEATURES and then ONE_CAR_GARAGE get initialized. Then, during the initialization of ONE_CAR_GARAGE, TESLA gets initialized since its enumeration class is referenced. All's well.
However, if we reference the enum too early then we do things in the wrong order. Recreate.Car.TESLA gets referenced, so TESLA gets initialized. TESLA references FEATURES, so Recreate has to be initialized. This causes FEATURES and ONE_CAR_GARAGE to get initialized before TESLA finishes existing.
It's that hidden dependency that trips you up. Recreate.Car depends on Recreate which depends on Recreate.Car. Moving the ONE_CAR_GARAGE field into the Garage class will cause it to not get initialized with FEATURES and will fix your problem.
class A {
static int super_var = 1;
static {
System.out.println("super");
}
}
class B extends A {
static int sub_var = 2;
static {
System.out.println("sub");
}
}
public class Demo{
public static void main(String []args){
System.out.println(B.super_var);
}
}
outputs are :
super
1
this means that the child class not going to load or any other thing? how is it works?
When you access the static fields of a super class on subclass reference, only the class that declares the field will be loaded and initialized, in this case it is A. This is specified in JLS §12.4.1 - When Initialization Occurs:
A reference to a static field (§8.3.1.1) causes initialization of only
the class or interface that actually declares it, even though it might
be referred to through the name of a subclass, a subinterface, or a
class that implements an interface.
Emphasis mine.
So in your code, class B would not even be initialized, and hence its static block would not be executed.
Checkout the answer to this question: In what order do static initializer blocks in Java run?
The static block gets called only when a class is accessed (either creating an instance or accessing a member field or static method). However, you access a member of class A only, so there is no reason for class B to be initialized yet. The static initializer of B will be called as soon as you access a member from that class (either a field or static method, or create an instance from class B).
The reason is that class B doesn't need to be initialized until you access one of its members. Because A doesn't know about B (and cannot access it) there's really no reason for B to initialize at that stage.
You will find out that when you access B.sub_var the static initializer of B will be executed.
I am trying to understand this example from Thinking in Java:
package c07;
import com.bruceeckel.simpletest.*;
class Meal {
Meal() { System.out.println("Meal()"); }
}
class Bread {
Bread() { System.out.println("Bread()"); }
}
class Cheese {
Cheese() { System.out.println("Cheese()"); }
}
class Lettuce {
Lettuce() { System.out.println("Lettuce()"); }
}
class Lunch extends Meal {
Lunch() { System.out.println("Lunch()"); }
}
class PortableLunch extends Lunch {
PortableLunch() { System.out.println("PortableLunch()");}
}
public class Sandwich extends PortableLunch {
private static Test monitor = new Test();
private Bread b = new Bread();
private Cheese c = new Cheese();
private Lettuce l = new Lettuce();
public Sandwich() {
System.out.println("Sandwich()");
}
public static void main(String[] args) {
new Sandwich();
monitor.expect(new String[] {
"Meal()",
"Lunch()",
"PortableLunch()",
"Bread()",
"Cheese()",
"Lettuce()",
"Sandwich()"
});
}
}
As I understand from Java Language Specification, the order of execution begins by loading the class containing the main method. Then all the statics and member variables of this class must be initialized (before which all the member variables of the superclasses must be intialized, although there are none of those in this case).
So I thought b, c, l would be initialized before main starts executing. That does not seem to be the case from the output though. Am I missing something?
No, b and c are instance variables.
There's no automatic instantiation of the class containing main. Only static variables are initialized. It's just as if some outside caller wrote:
Sandwich.main(args);
So when you wrote:
Then all the statics and member variables of this class must be initialized
... that was wrong. Only the static variables are initialized - just as normal.
The example output is correct. Here are the important rules:
when the class is created, the constructor of the super class has to be called first. This bubbles up to Object class
before the constructor is called, member variable initialization is called.
No statics are involved in this example, except the technical monitor.
JLS # 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.
JLS # 12.5. Creation of New Class Instances
Whenever a new class instance is created, memory space is allocated for it with room for all the instance variables declared in the class type and all the instance variables declared in each superclass of the class type, including all the instance variables that may be hidden (§8.3).
This question might be blunder to some of the Java Experts. But I would like to know why we create the objects in a static method like main but not in static block.
I understand that its going to create the object unnecessarily if we instantiate in static block and of course if we don't use it further. Are there any other things that are to be noted with this approach ? Can we relate this with Singleton Pattern ?
For example:
public class MyClass {
static {
AnotherClass object = new AnotherClass();
// Do Some operations here with object.
}
}
The main reason is control over when it actually gets executed.
The stuff in a static block will get executed the first time that the class is loaded and it's easy to accidentally cause a class to be loaded (for instance by referencing a constant on the class).
Having a static method means that you have complete control over when the method is called (because you have to explicitly call it).
In regards to singletons, the java idiom for eagerly loaded singletons initializes the instance as a static field. This will basically run just the same as a static block.
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
iI have some trouble getting sth like this to work in java:
public class ClassA {
public static ClassB PointerToB;
public static ClassC PointerToC;
public ClassA() {
PointerToB = new ClassB();
PointerToC = new ClassC();
PointerToB.doSthB();
}
}
public class ClassB {
public void doSthB() {
ClassA.PointerToC.doSthC();
}
}
public class ClassC {
public void doSthC() {
// ...
}
}
say i have these classes where my "main" class ("A") has several members. these pointers to other objects ("B", "C") are made static so code in "B" can access (non-static) methods in "C".
i know that static methods can only access other static methods and/or variables, but since the REFERENCE to these classes is static - and not the actual class itself - it should work fine this way - shouldn't it?
i'm a bit stuck here, since this kind of access crashes my application all the time :(
i need ClassB to access (non-static) methods in ClassC without passing all the references to A or C along. how do i do this?
Well, other than your constructor for ClassA being malformed (you're missing the brackets), that code compiles... but until you construct an instance of ClassA, both PointerToB and PointerToC will be null. If you want to just initialize them once, do so in static initializers - e.g. with the declarations:
public static ClassB PointerToB = new ClassB();
public static ClassC PointerToC = new ClassC();
Even so, there are two nasty bits of design here (IMO):
Public mutable fields are almost always a mistake
If everything uses ClassA.PointerToB and ClassA.PointerToC, you've effectively got singletons, with the accompanying downsides. Consider dependency injection instead.
When you say "you're stuck", do you mean you're getting NullPointerExceptions?
The variables PointerToB and PointerToC are static and will indeed be set by ClassA's constructor. However, this will only be run when an instance of ClassA is created.
What you were probably thinking of instead is a static initialiser block, which will be run when the class is loaded:
public class ClassA {
public static ClassB PointerToB;
public static ClassC PointerToC;
static {
PointerToB = new ClassB();
PointerToC = new ClassC();
}
public ClassA() {
PointerToB.doSthB();
}
}
Now whenever you access these variables they will be non-null. In this particular case, since you're not doing anything complicated, you may as well initialise them in the declaration:
public class ClassA {
public static ClassB PointerToB = new ClassB();
public static ClassC PointerToC = new ClassC();
}
This is functionally identical, but is arguably easier to write and understand.
Edit: As an aside, note that your code is actually quite nasty as it is now - there's a hidden temporal dependence, in that it would appear to work correctly so long as some bit of code constructed an instance of ClassA before you accessed the static variables. This could have worked quite happily (by coincidence) for months, before someone makes some tiny change (e.g. create a ClassA on demand rather than eagerly) and BANG, all of a sudden some completely unrelated code starts breaking.
Even worse than this temporal dependency, you're opening yourself up to race conditions that you probably hadn't even considered. Both of my versions above will guarantee that the static variables are initialised before you can do anything in the class, but this isn't the case with your version. You're setting them on each and every time that the class is constructed. If one thread's calling the constructor while another thread is accessing the variable, the results are undefined and could manifest as "random" crashes, weird data issues or other things.
Even if you avoid this, the actual object references will change over time, so you might call something like PointerToC.doSthC() (let's say it increments a counter in C) - this will correctly make the counter 1, but at a later point in the program, PointerToC has been reset to a new instance of ClassC and the counter is back at zero again!
I don't mean to show you up or anything by this, merely to point out how it's important to think about data consistency issues - and how just because something compiles, and in fact even if it works (right now) it's not necessarily correct.
i need ClassB to access (non-static) methods in ClassC without passing all the references to A or C along. how do i do this?
Then ClassB needs a reference to an instance of C - no real way around this.
Instead of ClassB accessing C via a static reference in A, why not write B a little differently?
public class ClassB {
public void doSthB(ClassC c) {
c.doSthC();
}
}
This cannot ever work. static means that different instances of a class can never have different values for a field, and yet that is exactly what you say you want to happen. Instead of making PointerToB static, provide the objects you use directly with references to the collaborators they need.
(You also seem confused about the difference between classes and objects. Try to give a non-generic example to receive more useful help here!)
I think the solution you're looking for is the singleton pattern:
public class ClassA{
private static final class InstanceHolder{
private static final ClassA INSTANCE = new ClassA();
private InstanceHolder(){
}
}
public static ClassA getInstance(){
return InstanceHolder.INSTANCE;
}
}
public class ClassB{
private static final class InstanceHolder{
private static final ClassB INSTANCE = new ClassB();
private InstanceHolder(){
}
}
public static ClassB getInstance(){
return InstanceHolder.INSTANCE;
}
}
that way, the classes are decoupled from each other (a bit), and you can access them independently:
// inside ClassA
public void doSthB() {
ClassB.getInstance().doSthC();
}
However, Singletons are evil, so be careful what you are doing. (But what you are doing now is arguably even more evil)