I couldn't find anything about this online, because I didn't know what to search for, but Java doesn't mark this code as having an error:
public class Test {
// ...
{
int test;
}
// ...
}
Does this serve any purpose in Java? If so, what?
This is called an instance initializer (JLS section 8.6)
When creating an object the instance initializer is run after super constructors but before the called constructor of the class they are defined in. See JLS 12.5 Creation of New Class Instances. Specifically, instance initializers are evaluated in step 4 of the object creation process. The key point is that instance initiailzers always get called no matter what constructor is used to instantiate the object.
There are also static initializers which are similar but marked with the static keyword.
public class Test {
static {
// Do something interesting on class load.
}
}
In my experience static intiailzers are more common as you can use them to setup complex class state (like linking JNI libraries) when the class is loaded.
Related
I have a question regarding static blocks:
Let's say i've got a class looking like this:
class SomeClass {
static {
System.out.println("static block");
}
}
and I define a variable of type SomeClass somewhere.
public static void main(String args[]) {
SomeClass foo;
}
Now i thought the static block would have been executed but it wasn't. As far as i know the static block is executed as soon as the classloader loads the SomeClass class. Now to my real question:
Isn't the class loaded as soon as I define a variable of that type?. If yes why isn't the static block executed?
If the answer should be no, then how can i know if a class has already been loaded by the class loader and what are the different possibilities to have the class loaded (I know of 2: initializing the variable & using a static field/method)
Refer to this doc: http://www.javaworld.com/article/2077260/learn-java/learn-java-the-basics-of-java-class-loaders.html
So when are classes loaded? There are exactly two cases: when the new bytecode is executed (for example, FooClass f = new FooClass();) and when the bytecodes make a static reference to a class (for example, System.out).
In your example, SomeClass foo; does neither execute the bytecode of SomeClass nor make a static reference to SomeClass. That's why the class is not loaded.
So following your example, add a static field in the class
public class SomeClass {
static {
System.out.println("static block");
}
static String abc = "abc";
}
SomeClass is loaded in either:
SomeClass foo = new SomeClass();
Or
System.out.println(SomeClass.abc);
Isn't the class loaded as soon as I define a variable of that type?.
Yes, it is loaded1, but it won't be initialized as a result of declaring a variable. However, when you create an instance of that type, or access a static field of that type, that is sufficient to trigger initialization, including the execution of static blocks.
See this related Q&A - When does static class initialization happen? - which lists all of the things that can trigger initialization.
How can i know if a class has already been loaded by the class loader and what are the different possibilities to have the class loaded (I know of 2: initializing the variable & using a static field/method)
The only ways I can think of for finding out when a class is loaded (as distinct from initialized) are:
turning on the JVM's class loader messages (using -verbose:class), or
using a customer classloader that notices, and does something appropriate when it sees a request to load the class.
A class is actually going to be loaded:
when it is explicitly loaded using Class.forName or similar, or a direct call to a classloader,
when it is necessary to load it in order to link another class, or
at JVM launch time, if the class is named as the entry point class.
The loading / linking / initializing steps are specified in Chapter 12 of the JLS.
1 - In fact, SomeClass needs to be loaded at the same time that the class containing that main method is linked; i.e. before the method containing that local declaration is called.
Say I have a static method increment:
public class StaticTest {
private static int no = 0;
public static void increment()
{
no++;
}
}
When I call increment using the StaticTest.increment() syntax, does the class ever get instantiated? What if no object of that type exists on the heap already?
When I call increment using the StaticTest.increment() syntax, does the class ever get instantiated?
The class, itself, is loaded (by the classloader), if it isn't already loaded. If it's already loaded, it is not loaded a second time. No instances of the class (objects of that class's type) are created, because you haven't created any.
Assuming all of the code that calls StaticTest.increment() is using the same classloader (which is normally the case), it doesn't matter how many different bits of code call that static method, just a single copy of the class is used. They all share it. E.g.:
// Some bit of code somewhere
StaticTest.increment();
// Another bit of code somewhere else
StaticTest.increment();
// A third bit of code in yet another place
StaticTest.increment();
Once all of those have run, the no private static member in StaticTest has the value 3.
What if no class of that type exists on the heap already?
Then then classloader loads it.
Contrast that code with this (no statics):
public class NonStaticTest {
private int no = 0;
public void increment()
{
no++;
}
public int getNo() // So we can see the results
{
return no;
}
}
Now, we can't do this:
NonStaticTest.increment(); // WRONG, fails with error saying `increment` is not static
We do this instead:
NonStaticTest instance = new NonStaticTest();
instance.increment();
System.out.println(instance.getNo()); // "1"
The first time code does that, the NonStaticTest class is loaded by the classloader. Then, the new NonStaticTest() expression creates an instance of the class, which has a no member. The second time code does that, NonStaticTest has already been loaded, so it's not loaded again. Then the new NonStaticTest() expression creates a second instance of the class.
If we had three bits of code all doing the above, each of them would see "1", because no is specific to an instance of the class rather than being attached to the class itself.
You have to clearly differentiate between 2 things:
classes, which are sort of "custom types" (I'm simplifying here)
objects, which are instances of these classes
Classes are loaded once by the classloader, whereas objects of a class are created each time you call new ClassName() (if the class is called ClassName).
Now, back to your problem: the use of the static keyword makes your declarations independant of any instance (object) of your class.
Therefore, when you use StaticTest.increment(), no object of the class StaticTest is created (and no object is needed).
You instantiate an instance with new StaticTest and unless you created one of those, you haven't created an instance.
This question already has answers here:
Use of Initializers vs Constructors in Java
(10 answers)
Closed 8 years ago.
I am studying for an exam about Java. While I was studying, I have encountered syntaxes in java which are unfamiliar to me. Such as a curly braces({}) unside a class body without a name, some has a static keyword. I have found out that they are called "Initializers". Can anyone help me point out key differences among them and how they differ from a Constructor. Thanks
The main difference between them is the order they are executed. To illustrate, I will explain them with an example:
public class SomeTest {
static int staticVariable;
int instanceVariable;
// Static initialization block:
static {
System.out.println("Static initialization.");
staticVariable = 5;
}
// Instance initialization block:
{
System.out.println("Instance initialization.");
instanceVariable = 10;
}
// Constructor
public SomeTest() {
System.out.println("Constructor executed.");
}
public static void main(String[] args) {
new SomeTest();
new SomeTest();
}
}
The output will be:
Static initalization.
Instance initialization.
Constructor executed.
Instance initialization.
Constructor executed.
Briefly talking:
Static initialization blocks run once the class is loaded by the JVM.
Instance initialization blocks run before the constructor each time you instantiate an object.
Constructor (obviously) run each time you instantiate an object.
A Constructor is called once when a new instance of a class is created. The values initialized in the constructor belong to the scope of the instance. Each Instance may have a different value for the same field initialized in the Constructor.
Static Initializers are useful for executing setup code in Static Classes and filling out data structures in Enums. They are called once, in order from top to bottom when the Class is loaded into the JVM and the data exists within the scope of the Class or Enum. All references to the Class will return the same value for fields initialized in the Static Initializers
Unnamed Curly Braces are Anonymous code blocks that scope reference names. If you create a reference inside the blocks, you can not get the value of that reference outside the block. If you find yourself needing them it's a sign you need to refactor your code into more methods.
This is the kind of thing you really need to look in your textbook to get an answer. However I can give you some pointers. Its been some years since I programmed Java, so any information I gave you is general.
Generally a nameless block with curly braces is an anonymous function. Static initializers initialize data that is global to all instances of that class, and runs once the first time the class is referenced. You need to be careful about how you use static properties or methods. With this information you can find accurate details in your text books.
By default, Sun's JVM both lazily loads classes and lazily initializes (i.e. calls their <clinit> methods) them. Consider the following class, ClinitBomb, which throws an Exception during a static{} block.
public class ClinitBomb {
static {
explode();
}
private static void explode() {
throw new RuntimeException("boom!");
}
}
Now, consider how to trigger the bomb:
public class Main {
public static void main(String[] args) {
System.out.println("A");
try {
Class.forName("ClinitBomb");
} catch (Exception e) {
e.printStackTrace(System.out);
}
System.out.println("B");
ClinitBomb o2 = new ClinitBomb();
System.out.println("C");
}
}
We're guaranteed the explosion happens before point B, since forName's documentation says so; the question is whether it happens before point A (when Main is loaded.) In Sun's JVM, even though main() contains a static reference to ClinitBomb, it happens after A.
I want a way to tell the JVM to load and initialize ClinitBomb as soon as it initializes Main (so the bomb explodes before point A.) In general, I want a way to say, "whenever loading/initializing class X, also do so for any classes Y it references."
Is there a way to do that?
There is no way to do this. The JLS says, in §12.4.1 When Initialization Occurs (emphasis mine):
Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class. [...]
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, and an assert statement (§14.10) lexically nested within T is executed.
Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.
A Java implementation which initialized classes as soon as they were loaded would violate the JLS.
Although what you could do would be to use the JVM instrumentation API to write a ClassFileTransformer which added a static block to every class which explicitly initialized its referenced classes (via Class.forName, probably). As soon as one class gets initialized, all the classes reachable from it will be initialized. That might give you the result you're after. It's quite a lot of work, though!
Class.forName("...", true /*initialize*/, getClassLoader());
You were halfways there.
I've read elsewhere that a static anonymous class doesn't make sense - that all anonymous classes should be tied to an instance of the enclosing type. But the compiler let's you do it. Here's an example:
class Test {
/*
* What's the difference at between
* Test.likeThis and Test.likeThat?
*/
// This is obviously okay:
private static final class LikeThat {
#Override
public String toString() { return "hello!"; }
}
public static Object likeThat = new LikeThat();
// What about this - is it really any different?
public static Object likeThis = new Object() {
#Override
public String toString() { return "hello!"; }
};
}
What's going on here?
From the Java Language Specification, section 8.1.3:
An instance of an inner class I whose declaration occurs in a static context has no lexically enclosing instances. However, if I is immediately declared within a static method or static initializer then I does have an enclosing block, which is the innermost block statement lexically enclosing the declaration of I.
Your anonymous class (the one likeThis is an instance of) occurs in a static context, so it is not tied to an enclosing instance. However, it seems that it can refer to final variables of its enclosing block (see the rest of section 8.1.3, they give an example).
Btw, your wording is a bit deceptive, you're actually referring to a static instance of an anonymous class (it's the instance that's static, not the class).
I see nothing wrong with static anonymous classes
Like anything in any language you should just consider why you're doing it. If you've got alot of these instances then I'd question the design decisions, but it doesn't necessarily means it's a pattern that should never be followed.
And of course, always consider the testability of the class and whether you can provide a test double if the need arises
I don't think they have no sense. If you don't need reference to enclosing object then it's better to leave it static. Later it can evolve in separate class with ease.
Wide-spread enum idiom (pre Java 5) used similar approach with anonymous static inheritors of enum class. Probably, now it is better stick to Java 5 enum for this case.
If you are able to find adequate real-world application for anonymous static classes - why not to use them?
I do this all the time. It's especially handy for special-case implementations of utility interfaces, e.g.:
/** A holder for {#link Thing}s. */
public interface ThingsHolder {
/** A {#link ThingsHolder} with nothing in it. */
public static final ThingsHolder EMPTY_HOLDER = new ThingsHolder() {
#Override
public Iterable<Thing> getThings() {
return Collections.emptySet();
}
};
/** Provides some things. */
Iterable<Thing> getThings();
}
You could create a private static inner class called EmptyHolder, and maybe in some cases that would make the code more readable, but there's no reason you have to do it.
According to this answer which references the JLS, anonymous classes are never static, but when created in a "static context" they have no "enclosing instance".
That said,
They give the same error at compile time if you try to reference Test.this (non-static variable this cannot be referenced from a static context)
At runtime, the only obvious difference between the Class objects (apart from name) is that Test$1 is an "anonymous class" and Test$LikeThat is a "member class". Both of them have an enclosing class; neither of them have an enclosing constructor or method. (I only checked the likely-looking methods; there may be other differences.)
EDIT: According to getModifiers(), Test$1 is static and Test$LikeThat is static final! According to the language spec, Test$1 should actually be final. Hmm...
According to javap -c -verbose -s -private -l,
Test$1 specifies an "EnclosingMethod" (probably Test's static initializer?)
Test$LikeThat has an extra entry under "InnerClass" (#12; //class Test$1) and a curious constructor Test$LikeThat(Test$1). This appears to happen because LikeThat is private which makes the constructor private, so the compiler generates a "trampoline" to allow it to be called from Test.
If you remove the private, they appear to compile to roughly the same thing apart from the EnclosingMethod entry.
Test$1 does not have the field final Test this$0; that it would if it was defined in a non-static context.
Seems perfectly legitimate to me. Since the anonymous class is static it won't have a reference to any enclosing class, but there should be no evil consequences from that.
Well, other than being a hidden singleton object, that's pretty evil.
Of course they are not. I always use static nested classes, unless I need the implicit association to the enclosing object.
In java terminology nested class := a class which is declared within another class (or interface). Inner classes are those nested classes which have an associated instance from the enclosing class. (Nonstatic member classes, local classes, anonymous classes).
The implicit association can prevent garbage collection sometimes.
These can be very convenient because of possibility to make circular references:
class A
{
public static final A _1 = new A() {
public A foo()
{
return _2;
}
};
public static final A _2 = new A() {
public A foo()
{
return _1;
}
};
}
Creation of several objects which are holding references to each other can be very awkward without usage of anonymous classes.