So I'm looking at a Java project for my university and the code we are working with has this syntax that I have never seen before:
public abstract class Machinery {
protected String name="default Computer";
protected int weight=0;
protected static int num_of_Machineries;
//int counter=0;
static String kevo=" ";
{
num_of_Machineries++;
System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
System.out.println("Machinery construction call Baby!");
print(this);
}
}
From what I understand, this works like a default constructor. Can anyone confirm or deny my suspicions?
That's an instance initializer.
It's effectively a block of code that is inlined into the start of constructors (*), rather than being a constructor itself.
Since this class has no explicit constructor, the compiler gives it a default constructor. Default constructors invoke super(), so the instance initializer is inlined into it.
It's effectively the same as:
public abstract class Machinery {
protected String name="default Computer";
protected int weight=0;
protected static int num_of_Machineries;
//int counter=0;
static String kevo=" ";
public Machinery() {
// Invoke the default super constructor.
super();
// Inline body of instance initializer.
num_of_Machineries++;
System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
System.out.println("Machinery construction call Baby!");
print(this);
// Rest of constructor body (which is empty).
}
}
Unless you have a very good reason (**) to use an instance initializer (and I'll say you don't, if you don't know what one is), it is better to define an explicit constructor and put the code from the instance initializer in there.
Note: you probably don't want to execute print(this); in the initializer/constructor: at the time this is executed, your instance isn't fully initialized, so this might have some unexpected effects.
(*) It is inlined into all constructors which (implicitly or explicitly) invoke super(...);. It is not inlined into constructors which invoke this(...);, because those have to (eventually) invoke a constructor invoking super(...);, and you only want the initializer code to be executed once.
(**) The only good reason I can think of is to avoid having to duplicate code between two or more super(...)-invoking constructors; but even then, you can often write it with methods. The only time where you really can't do it without an instance initializer is where there are multiple super(...)-invoking constructors which initialize co-dependent final fields. Rare, and probably a sign you should rethink the class.
Related
I was learning about using this() to call an overloaded constructor and came across this restriction:
You can not use any instance variable of the constructor's class in a call
to this()
For example:
class Test{
int x;
public Test() {
this(x); //Does not compile
}
public Test(int y) {}
void method1() {
method2(x); //OK
}
void method2(int y) {}
}
I know that no need to pass an instance field to a constructor since it's visible by default. However, why is the same restriction not applied to instance methods?
There is one other requirement in Java: constructor calls (using this() must be performed first within any constructor. The constructors will initialize the object.
After that the instance fields are initialized after these initial calls. So as the field values are now well defined, you can use them for anything including calling other methods.
However, before the initial constructor calls, the fields are in an undefined state and cannot be used as argument for other constructor calls.
For these kind of things you need to look in the JLS:
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
So the instance variables are only initialized after the constructor calls. This makes sense, because it would be strange to first assign it the default value (zero or null) and then assign it another value from within a constructor.
The constructor constructs the instance. So we shouldn't expect the instance variable x to be initialized at the time the constructor starts.
On the other hand, an instance method can already access instance variables. There is no reason to forbid passing them as a parameter into another instance method.
However, when we start to think about it a bit further, that restriction on the constructor doesn't make that much sense anymore. We are able to access instance variables there as well, so why shouldn't we be able to pass it a parameter to another constructor?
So a better question to ask is: Why can't we pass an instance variable to call an overload of our constructor from within our constructor?
And this question has been beautifully answered. It could even be considered a duplicate (but since that pretext is neccessary to understand why, I wrote an answer instead of simply flagging).
The instance fields that are declared and initialized in the class body outside of the constructor, like your int x; are assigned after the call to the overloaded constructor.
You can compare that to the other restriction we have about calling constructor overloads: We can only do so in the first line of our constructor. Right at the start. And then, the variables are not yet initialized. But they are initialized right before the first non-constructor-call instruction.
Tangential information to why this other restriction is a thing can be found here and there:
Because the JLS says so. Could the JLS be changed in a compatible manner to allow it? Yup.
Historically, this() or super() must be first in a constructor. This
restriction was never popular, and perceived as arbitrary. There were
a number of subtle reasons, including the verification of
invokespecial, that contributed to this restriction. Over the years,
we've addressed these at the VM level, to the point where it becomes
practical to consider lifting this restriction, not just for records,
but for all constructors.
You should be educating the class order initialization f.e: https://www.baeldung.com/java-initialization
The int x field is not initialized when the class constructor is called. You can set (initialize) `int x 'in your constructor, but not call it.
I don't know why you have to follow this way, but you can use the static field:
class Test{
static int x;
public Test() {
this(x); //Does not compile
}
public Test(int y) {}
void method1() {
method2(x); //OK
}
void method2(int y) {}
}
You can also initialize a static field in the line where it is called,
static int x =4/2;
or in static block:
static int x;
static {
x = 4/2;
}
I have read in many sources and books that constructor is used to initialise the fields when an object is created. I have also read that JVM provides a default constructor if I don't mention one. What is the purpose of a constructor if it is not required to initialise the fields like the one I have mentioned below?
I also understand that a constructor without parameter is required as
it is necessary during object creation when an argument is not passed
(when programmer-defined constructors with parameters exists).
Is it necessary for JVM to provide a constructor which is actually not required?
public class test {
int a;
public test() {
//this constructor is useless
}
public static void main(String[] args)
{
test ob= new test();
System.out.println(ob.a);
//this prints 0 which means a constructor is not required in intialising `a`
}
}
A constructor like test() makes sense if the programmer defines it since there could be other constructors which takes argument.
But why is it necessary for JVM to provide one when no constructor is declared by the programmer?
I have already tested and proved that initialising a field doesn't require constructor.
Also what does the default constructor look like?
The problem is that while you know the default constructor doesn't do anything in this example, in future the constructor might do something even if you don't realise it is and you might not be able to re-compile everywhere the code is used reliably. So the safest, simplest thing to do is to always call a constructor which might change in the future and let the JIT optimise away the constructor if it doesn't actually do anything.
The byte code always calls a contructor, whether you provide one or not. When you compile code which uses the default constructor it cannot assume the constructor doesn't do anything useful as you can add something to it later to do something useful. e.g.
Say you change
public class Test {
int a;
// public Test() { //this constructor does nothing
}
to
public class Test {
int a;
final List<String> strings = new ArrayList<>();
// public Test() { //this constructor does something now.
}
or
public class ServerTest {
final List<String> strings = new ArrayList<>();
}
public class Test extends SuperTest {
int a;
// the default constructor has to call super();
}
The constructor now initialised the strings field. You can change this class without having to re-compile everywhere it is used and say, hey, my constructor now does something useful, you should call it now.
The reason the JVM adds a default constructor if you haven't provided one is down to inheritance. Say for example you have 3 classes (A, B & C) in which B extends A and C extends B. Now when you instantiate C it will call the constructor of C and also the constructors of B and A. If a constructor was missing in one or more of these classes then the instantiation would fail. So having the compiler automatically add a default constructor avoids error like this. You may not need to actually do any work in your constructor, but it's required for the JVM to instantiate the object.
The constructor(s) (both default and custom one(s)) is not only used to initialize the fields of an object but also to initialize the object itself even if it has no fields at all. Calling the constructor, JVM allocates memory for this object and creates its reference.
It is the compiler, and not JVM, who inserts a default constructor on absence.
A default constructor is needed because the constructor of the base class needs to be called from a constructor.
The default constructor looks like:
public Test() {
super();
}
Here while you are creating the object new test(),
here parenthesis states the default constructor of object test.After creating the object,if you didnot give any constructor the default constructor is constructed by jvm.so after construction of your object first call goes to your default constructor.
The default constructor is a no argument constructor called automatically by the compiler when you haven't defined any constructor. Anyway, a constructor as the one you defined, can be also called a default constructor.
It basically calls the superclass' constructor making use of the super() method.
So the default constructor called automatically would be something like:
public ClassName(){
super();
}
Java's Compiler creates a Default Constructor if no other constructor is defined for the class.
But why?
The compiler's job is to chain the Subclass's constructor to the Super Class(ultimately Object class). It's not the Compiler's work to give a default constructor to your class therefore Java is doing it for you.
To do the chaining, it first checks if there is any constructor in the class, if yes it will add super() to that constructor.
If there is no constructor idefined in the class in order for the compiler to do a proper chaining, Java adds a default constructor and a call to super() into it.
Why ?
Because every class is a subclass of an Object class (directly or indirectly), it will inherit an object class, to do so the said Object class must be fully initialised. This is done by the default constructor.
I am just trying to figure out why it is possible to do such thing but it is not possible in some other programming languages like C++.
Here is an example of what I am asking:
public class A{
private A objectOfTheSameClass;
public A()
{
objectOfTheSameClass=new A();
}
}
Because it's not explicitly prohibited.
JLS section 8.8.7 that defines that body of a constructor does not mandate a compile-time error for such a case. The only case when a compile-time error should happen is when a constructor invokes itself with this:
It is a compile-time error for a constructor to directly or indirectly invoke itself through a series of one or more explicit constructor invocations involving this.
More precisely:
Except for the possibility of explicit constructor invocations, and the prohibition on explicitly returning a value (§14.17), the body of a constructor is like the body of a method (§8.4.7).
Since a method is allowed to invoke itself (recursion), a constructor is also allowed to do the same.
This will not compile because it calls this:
public class A{
private A objectOfTheSameClass;
public A() {
objectOfTheSameClass= this();
}
}
Your code, although it compiles, will throw a StackOverflowError because the constructor of A creates itself a new instance of A. The compiler can't detect every infinite loop in your code...
It can be useful sometimes, for example in the "singleton" pattern is used to have exactly one instance of a class by creating an object of the same class as a class field, making it accessible via a public method and making the constructor private.
The instances are not created until the runtime, so the class is fully defined. It's up to you to use this in a proper way.
I have a class whose initialization takes quite a bit of time; it invokes a server and that server takes several minutes to become ready.
Methods on that class aren't called for quite a while and they are always called from a class that is automatically loaded on start-up. My set-up is like this:
class SlowToStartUp {
public static void init() {
// do nothing
}
static {
initiateConnectionToServer()
}
public static V invokeServer() {
waitForServerToConnect();
return valueFromServer();
}
}
class AlwaysLoaded {
static {
SlowToStartUp.init();
}
public void someMethod() {
V v = SlowToStartUp.invokeServer();
}
This strikes me as structurally correct. If there were no init() function at all, initiateConnectionToServer() wouldn't be called until someMethod() needed the class for the first time, and then there would be an unnecessary (and in my system, unacceptable) delay.
If I put the initiateConnectionToServer() call in init(), the interface would be more fragile (since the call might be forgotten).
But now I am wondering if I have outsmarted myself. The compiler can see that init() is empty. Could it not just optimize the call away? It does not do so now, but it that guaranteed?
I tried marking init() as volatile, but that is not allowed.
I am considering putting the actual initialization into init(), making sure it is idempotent, and invoking it from a static block, just to be on the safe side, but I thought I would ask for advice first.
One alternative approach would be to refactor to a singleton class instead of a bunch of static method. The singleton will then be created at startup and your initialization code would run right away.
public class SlowPokeSingleton {
private SlowPokeSingleton() { /* execute init code */ }
// created at startup
private final static SlowPokeSingleton instance = new SlowPokeSingleton();
public static SlowPokeSingleton instance() { return instance; }
}
You will need to call instance() to make sure the instance is actually created. You can add that to your server startup to be safe.
I have a tenuous answer to my own question. The events that trigger class initialization are specified in JLS 12.4.1.
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.
It seems to me that a compiler that optimized away an empty static function would violate the provision I marked in bold.
Comments welcome.
I agree with Giovanni Botta:
You could use a singleton pattern instead of static methods and fetch
the singleton instance as soon as your application starts. That would
force the JVM to create the instance and thus run your initialization
code. – Giovanni Botta
Specifically:
1) Put the "time consuming" part of your initialization into a private, static "init()" method.
2) Make your class's constructor "private".
3) Instead of a constructor, provide a public static "getInstance()" method to fetch a reference to your (already-initialized) singleton instance.
4) Your other methods can be non-static, if you wish.
I would appreciate help in understanding the following from 'Java Concurrency in Practice':
Calling an overrideable instance method(one that is neither
private nor final) from the constructor can also allow the
this reference to escape.
Does 'escape' here simply mean that we may probably be calling an instance method,before the instance is fully constructed?
I do not see 'this' escaping the scope of the instance in any other way.
How does 'final' prevent this from happening?Is there some aspect of 'final' in instance creation that I am missing?
It means calling code outside the class, and passing this.
That code will assume that the instance is fully initialized, and may break if it isn't.
Similarly, your class might assume that some methods will only be called after the instance is fully initialized, but the external code is likely to break those assumptions.
final methods cannot be overridden, so you can trust them to not pass this around.
If you call any non-final method in the constructor for a non-final class, a derived class might override that method and pass this anywhere.
Even when you call final methods, you still need to make sure that they are safely written – that they do not pass this anywhere, and that themselves don't call any non-final methods.
"Escape" means that a reference to the partially-constructed this object might be passed to some other object in the system. Consider this scenario:
public Foo {
public Foo() {
setup();
}
protected void setup() {
// do stuff
}
}
public Bar extends Foo implements SomeListener {
#Override protected void setup() {
otherObject.addListener(this);
}
}
The problem is that the new Bar object is being registered with otherObject before its construction is completed. Now if otherObject starts calling methods on barObject, fields might not have been initialized, or barObject might otherwise be in an inconsistent state. A reference to the barObject (this to itself) has "escaped" into the rest of the system before it's ready.
Instead, if the setup() method is final on Foo, the Bar class can't put code in there that will make the object visible before the Foo constructor finishes.
I believe the example is something like
public class Foo {
public Foo() {
doSomething();
}
public void doSomething() {
System.out.println("do something acceptable");
}
}
public class Bar extends Foo {
public void doSomething() {
System.out.println("yolo");
Zoom zoom = new Zoom(this); // at this point 'this' might not be fully initialized
}
}
Because the super constructor is always called first (either implicitly or explicitly), the doSomething will always get called for a child class. Because the above method is neither final nor private, you can override it in a child class and do whatever you want, which may conflict with what Foo#doSomething() was meant to do.
Per secure coding
Example BAD code:
final class Publisher {
public static volatile Publisher published;
int num;
Publisher(int number) {
published = this;
// Initialization
this.num = number;
// ...
}
}
If an object's initialization (and consequently, its construction) depends on a security check within the constructor, the security check can be bypassed when an untrusted caller obtains the partially initialized instance. See rule OBJ11-J. Be wary of letting constructors throw exceptions for more information.
final class Publisher {
public static Publisher published;
int num;
Publisher(int number) {
// Initialization
this.num = number;
// ...
published = this;
}
}
Because the field is nonvolatile and nonfinal, the statements within
the constructor can be reordered by the compiler in such a way that
the this reference is published before the initialization statements
have executed.
Correct code:
final class Publisher {
static volatile Publisher published;
int num;
Publisher(int number) {
// Initialization
this.num = number;
// ...
published = this;
}
}
The this reference is said to have escaped when it is made available
beyond its current scope. Following are common ways by which the this
reference can escape:
Returning this from a non-private, overridable method that is invoked from the constructor of a class whose object is being
constructed. (For more information, see rule MET05-J. Ensure that
constructors do not call overridable methods.)
Returning this from a nonprivate method of a mutable class, which allows the caller to manipulate the object's state indirectly. This
commonly occurs in method-chaining implementations; see rule VNA04-J.
Ensure that calls to chained methods are atomic for more information.
Passing this as an argument to an alien method invoked from the constructor of a class whose object is being constructed.
Using inner classes. An inner class implicitly holds a reference to the instance of its outer class unless the inner class is declared
static.
Publishing by assigning this to a public static variable from the constructor of a class whose object is being constructed.
Throwing an exception from a constructor. Doing so may cause code to be vulnerable to a finalizer attack; see rule OBJ11-J. Be wary of
letting constructors throw exceptions for more information.
Passing internal object state to an alien method. This enables the method to retrieve the this reference of the internal member object.
This rule describes the potential consequences of allowing the this
reference to escape during object construction, including race
conditions and improper initialization. For example, declaring a field
final ordinarily ensures that all threads see the field in a fully
initialized state; however, allowing the this reference to escape
during object construction can expose the field to other threads in an
uninitialized or partially initialized state. Rule TSM03-J. Do not
publish partially initialized objects, which describes the guarantees
provided by various mechanisms for safe publication, relies on
conformance to this rule. Consequently, programs must not allow the
this reference to escape during object construction.
In general, it is important to detect cases in which the this
reference can leak out beyond the scope of the current context. In
particular, public variables and methods should be carefully
scrutinized.