In this code I see the following lines before the "main" method:
JTextArea displayArea;
JTextField typingArea;
I wonder what these lines do and when they are executed. As far as I know the "main" method is the "entry point". So, the code will be executed from the beginning of the "main" method. All other methods will be executed if they are called from the "main" method. If it is so, the mentioned 2 lines will never be executed. Moreover, even if they will be executed, what exactly they do? What do these pairs of "ClassName objectName" do?
Those are called "declarations". They are declaring the existence of two variables, stating their types and their names. The location of the declaration determines their scope, in other words, which parts of the program are allowed to know about those particular variables, and may refer to them.
Here's a tutorial about Java variables.
You haven't included the whole file.
These are the declarations of fields. It indicates that when the class is instantiated (i.e., an object is created from it), each object will have a reference to a text area and a text field. You will, however, have to create these objects.
Notice how your main method is static. This means that it can run without the containing class being instantiated. However, most Java methods operate on objects. Suppose that your main is in class C. It is likely that somewhere in your main, you will see a "new C" which means that an instance of C is created. Then some other operation will be invoked on that new object (look for other, non-static methods in the file), and these operations will manipulate these two fields.
it specifies the types.
JTextArea displayArea; // this creates textarea type and thus textbox
JTextField typingArea; // thus creates textfield type var and thus text field
These are members (reference) variables of the KeyEventDemo class.
When KeyEventDemo is instantiated using the new keyword, each instance will have a these variables to refer to a JTextArea and JTextField respectively. These are initialized to null and are assigned as references to a couple of instances in the addComponentsToPane method.
Those declarations are evaluated when the object is instantiated by the java virtual machine. That is right before the main methode is this case.
Those are class members.
Basically, in a java class, you have methods and members. The members are variables that hold the state of Objects that are instances of that class.
The main method is separate, it's a static method so it can run without there being an instance of the class. So you have logic that runs in main() and you have logic that runs on an instance of the class. They're quite separate.
If you want too, in your main() function you can create an instance of the class, and then that could would 'run' if there is any initialization of the member functions that needs to be done.
However, not all class members are initialized in the constructor, and those would stay null (so in that case, nothing would 'execute' at that point). In your example, there's no initialization, so those members would be null when the constructor logic starts.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Would you:
add types above the main method and then initialize them under the method
public class Main {
private Person person;
public void method() {
person = new Person("Bob", 30);
add types above the main method AND initialize them
public class Main {
private Person person = new Person("Bob", 30);
public static void main(String[] args) {
add types under the main method AND initialize them
public class Main {
public static void main(String[] args) {
Person person = new Person("Bob", 30);
I would like to know when you would use which way and why.
I appreciate any input!
a) The private modifier is not allowed inside a method, so your third example will not even compile.
b) Only your 2nd example actually compiles. The first one has a non-static member of class "Main" and you try to set it directly inside a static method.
c) The examples are not equal. The third one has a local variable in the method (assuming we ignore the private modifier), the other two have a member variable of "Main".
a&b vs. c depends on where you need your variable. If you only need it inside the method, declare it there.
a vs. b depends primarily on what readability and use cases. If you CAN initialize your variable there and if it doesn't lead to unreadable code, do it. Otherwise, do it in the constructor or any init method.
Personally, I tend to mostly declare final objects directly, non-final objects can be initialized elsewhere (because declaring them directly makes it look pretty final even if they aren't).
This is not a question of common practice, because the three examples you gave actually have different meanings. So it's more a matter of understanding variable declarations.
A variable declaration is declaring the name, type and optionally, the initial content of a variable you need to use.
String s = "abc";
↑ ↑ ↑
type name initializer
Now take a look at a class definition:
class A {
// Class body scope
}
Everything declared inside a type body (class, interface, enum) is a member of that type. Members include fields, methods and nested classes. Variable declarations in this scope (outside of any method) are fields, and they can be instance fields and static fields. If they have the modifier static, they are shared by all the members of the class and in fact can be used without having an actual instance of this class. If they don't have that modifier, then they are instance fields.
Instance fields can't be used without having an actual instance. So they are not available to static methods like main, only to instance methods. Thus, your first example won't work - main is trying to put a value in an instance field (as it doesn't have the word static).
In the second example, you're still creating an instance field, but this time you are giving it an initial value. This is fine - but you still won't be able to access this information from main. This is merely a field that will exist separately in every new Main object you will create (if you create one).
In the third example, you are creating the variable inside a method. In this case, the variable is not a field. It is a local variable. As such, it cannot have access modifiers such as private and public, because local variables are only accessible inside the method where they are declared (in fact, inside the block where they are declared).
But if you remove the access modifier, this will work, and you'll be able to use it in main, but not outside of main.
Generally, the question whether to give the variable an initializer or assign to it later on depends on whether it's a field or a local variable, whether it is final or not, static or not, and whether you have a meaningful value for it when you create it. For local variables, it's recommended:
To declare it as close as possible to where it is going to be used.
To give it a value as soon as a meaningful value can be given.
In practice this means that most of the time you'll have an initializer in local variable declarations, if only to avoid pesky "variable may not have been initialized" compiler warnings.
For fields, especially if they are declared final, you're going to need to initialize them as soon as possible, but not necessarily with an initializer. You might do so in a constructor (for an instance field), or in an initializing block (for a static field whose value needs to be determined by a complex operation).
If the only place you need tha variable 'person' is your Main method, you should declare and initialize 'person' as you did in the third example.
If you need that somewhere else, I would say you can do whatever you want to, but don't switch between those to make your code readable.
Why we instantiate some object inside constructor and some outside. What are the advantage/ disadvantages of doing this.
public class HomePage_Util {
private Common_Functions cfObj = new Common_Functions();
HomePage_OR home_ORobj;
Logging logObj = new Logger();
public static String scptName;
public ArrayList<String> homeScriptMsgList = new ArrayList<String>();
public HomePage_Util(WebDriver driver) {
home_ORobj = new HomePage_OR();
PageFactory.initElements(driver, home_ORobj);
}
Objects are initialized in constructors only when they are needed to initialize other objects in a sequence. Like in your example first of all the object i.e. home_ORobj = new HomePage_OR(); will be created as this object is needed to initialize the PageFactory elements in next step.
So if home_ORobj = new HomePage_OR(); is not needed to initialize the PageFactory elements then you could write it out of the constructor i.e. globally.
Code reuse is the main advantage of initializing elements in a constructor. Also initializing few things makes sense only when the object is created or constructor is called.
Constructor is basically for creating a new object of a class. When you create an object, a copy of all variable for that object is created and assigned default value.
The purpose of initiating some variables in constructor is to assigned the value at the time of creation of an object. So that you don't have to assigned value implicitly.
My guess is the writer of such code wasn't sure if home_ORobj would be initialized before the call to initElements() but the ones outside are initialized first so it doesn't matter.
Though if they depend on each other (i.e. use another in the parameters to the constructor) it's good to put them in the constructor as code formatters may re-order the list of elements breaking the the code.
Some objects requires few fields to be initialised in order to correctly construct that object before it being used. Constructor is called when the object is getting created, hence it is initialised in constructor.
You can have overloaded constructor with different initialistion for different scenarios.
You can always have a method called initializeValues and call it after you create an object rather than putting it in constructor.
Putting it in constructors will ensure that it is always called when you create an object.
Super class constructor is always called before the derived class constructor, so it makes sense.
One advantage is to avoid a static block to initialize static members.
AFAIK It's not exactly the same in the lifecycle of an object : constructor is executed after the firsts initializations.
An instance field that is initiated outside a constructor is always going to be that way initially when a new object is created - for every instance. The ones initiated in a constructor may have some special meaning for the new instance such as the WebDriver in your example seems to have so it cannot be initiated elsewhere. A constructor that requires an instance of certain type to be passed as an argument does enforce design since it cannot be passed anything else and cannot be constructed without it.
A class may contain multiple constructors that may behave differently and instantiate different fields and leave others untouched (like when there are multiple purposes for a class, which actually may indicate bad design).
Additionally, if a class does not have a default constructor => upon deserialization no constructor's get called.
I used to think that, intuitively speaking, a constructor in Java is the thing that makes an object, and that nothing can touch that object until its constructor returns. However, I have been proven wrong about this over and over again:
uninitialized objects can be leaked by sharing this
uninitialized objects can be leaked by a subclass accessing it from the finalizer
uninitialized objects can be leaked to another thread before they're fully constructed
All of these facts violate my intuition of what I thought a constructor is.
I can no longer with confidence say what a constructor actually does in Java, or what it's meant to be used for. If I'm making a simple DTO with all final fields, then I can understand what the use of the constructor is, because this is exactly the same as a struct in C except it can't be modified. Other than that, I have no clue what constructors can be reliably used for in Java. Are they just a convention/syntactic sugar? (i.e If there were only factories that initialize objects for you, you would only have X x = new X(), then modify each field in x to make them have non default values - given the 3 facts above, this would be almost equivalent to how Java actually is)
I can name two properties that are actually guaranteed by constructors: If I do X x = new X(), then I know that x is an instance of X but not a subclass of X, and its final fields are fully initialized. You might be tempted to say that you know that constructor of X finished and you have a valid object, but this is untrue if you pass X to another thread - the other thread may see the uninitialized version (i.e what you just said is no different than the guarantees of calling a factory). What other properties do constructors actually guarantee?
All of these facts violate my intuition of what I thought a constructor is.
They shouldn't. A constructor does exactly what you think it does.
1: uninitialized objects can be leaked by sharing this
3: uninitialized objects can be leaked to another thread before they're fully constructed
The problem with the leaking of this, starting threads in the constructor, and storing a newly constructed object where multiple threads access it without synchronization are all problems around the reordering of the initialization of non-final (and non-volatile) fields. But the initialization code is still done by the constructor. The thread that constructed the object sees the object fully. This is about when those changes are visible in other threads which is not guaranteed by the language definition.
You might be tempted to say that you know that constructor of X finished and you have a valid object, but this is untrue if you pass X to another thread - the other thread may see the uninitialized version (i.e what you just said is no different than the guarantees of calling a factory).
This is correct. It is also correct that if you have an unsynchronized object and you mutate it in one thread, other threads may or may not see the mutation. That's the nature of threaded programming. Even constructors are not safe from the need to synchronize objects properly.
2: uninitialized objects can be leaked by a subclass accessing it from the finalizer
This document is talking about finalizers and improperly being able to access an object after it has been garbage collected. By hacking subclasses and finalizers you can generate an object that is not properly constructed but it is a major hack to do so. For me this does not somehow challenge what a constructor does. Instead it demonstrates the complexity of the modern, mature, JVM. The document also shows how you can write your code to work around this hack.
What properties are guaranteed by constructors in Java?
According to the definition, a constructor:
Allocates space for the object.
Sets all the instance variables in the object to their default values. This includes the instance variables in the object's superclasses.
Assigns the parameter variables for the object.
Processes any explicit or implicit constructor invocation (a call to this() or super() in the constructor).
Initializes variables in the class.
Executes the rest of the constructor.
In terms of your 3 issues, #1 and #3 are, again, about when the initialization of non-final and non-volatile fields are seen by threads other than the one that constructed the object. This visibility without synchronization is not guaranteed.
The #2 issue shows a mechanism where if an exception is thrown while executing the constructor, you can override the finalize method to obtain and improperly constructed object. Constructor points 1-5 have occurred. With the hack you can bypass a portion of 6. I guess it is in the eye of the beholder if this challenges the identity of the constructor.
From the JLS section 12.5:
12.5. Creation of New Class Instances
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
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.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If
this constructor is for a class other than Object, then this
constructor will begin with an explicit or implicit invocation of a
superclass constructor (using super). Evaluate the arguments and
process that superclass 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 4.
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.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly
for the same reason. Otherwise, this procedure completes normally.
**
Unlike C++, the Java programming language does not specify altered rules for method >dispatch during the creation of a new class instance. If methods are invoked that are >overridden in subclasses in the object being initialized, then these overriding methods >are used, even before the new object is completely initialized.
And from JLS 16.9:
Note that there are no rules that would allow us to conclude that V is
definitely unassigned before an instance variable initializer. We can
informally conclude that V is not definitely unassigned before any
instance variable initializer of C, but there is no need for such a
rule to be stated explicitly.
Happens before 17.4.5:
Threading 17.5.2:
A read of a final field of an object within the thread that constructs
that object is ordered with respect to the initialization of that
field within the constructor by the usual happens-before rules. If the
read occurs after the field is set in the constructor, it sees the
value the final field is assigned, otherwise it sees the default
value.
A class contains constructors that are invoked to create objects from the class blueprint.
This is what Oracle says about constructors.
Now to your point.
intuitively speaking, a constructor in Java is the thing that makes an object, and that nothing can touch that object until its constructor returns.
So according to the official documentation, your assumption is not right. And the point 1 and 2 are the abuse of the rules and behaviors of Java, unless you consciously want to leak your objects! As also being irrelevant to Constructor, I will skip discussing these points.
Now if we talk about your 3rd point, in multi-threaded environment there is nothing that can guarantee you about the consistency of your code, unless "properly synchronized blocks" or "the atomic instructions". As object creation is not a synchronized nor an atomic instruction, there is no guarantee of being consistent! There is nothing the Constructor can do with it. In other words its not the responsibility of the Constructor to make your object creation atomic.
Now, the answer to your question, "What other properties do constructors actually guarantee?" is somewhat easy. Constructors are merely nothing but special type of methods, that are invoked during object creation from the blue print of the class. So it can guarantee nothing, unless you give it a chance to be executed consistently like any other methods. It after being consistently executed it can guarantee you that, your object is created and initialized as you wanted and instructed in it.
constructors is java are just used to initialize the state of the object created..nothing more.
I'm confused with variable declarations in Java code.
I read... don't try to use global variables declarations .
Don't use something like this:
package cls;
public class test {
private String var;
public someMethod(){ ... }
}
And use ?
package cls;
public class test {
public someMethod(){
String var = null;
}
}
I don't know which is the correct way....
It totally depends on what you need.
Your first example, however, isn't a global variable--it's an instance variable.
Variables should have as small a scope as possible. This makes code easier to reason about.
Instance variables are central to what OOP is all about--classes (objects) exist to encapsulate object state, and the methods that operate on that state. For example, a Person class would likely have first and last name instance variables:
public class Person {
private String firstName;
private String lastName;
// Plus getters and setters for each.
}
This allows instance methods to access the first and last name variables directly without having to pass them between all the methods that need them.
The second example is a local variable. It's visible only in the method it's declared in. A reference to it may be passed to other methods.
Both are correct. Neither of those are global variables. The first one is a class field. It's unique to each instance of the class that you make. Class fields (ie. variable) stay with the instance of the class until the class itself is deleted.
The second one is a method scope variable. It's only there for temporary purposes to perform the calculations needed for the method to work, and once the code in the method is done, the variable goes away.
You use each for different purposes. For example, if you're writing a Car class, you'd probably have a class field for SteeringWheel and Brake. But if you had a method to calculate the average miles per gallon, you might create a method scoped variable to help perform the calculation.
Java doesn't have global variables. The first variable is class level and maintains the state of class instances and hence exists as long as an instance of the class while the second is a method's local variable that exists only during method's execution. You can use the first variable to store state information that spans multiple method calls. The second variable disappears as soon as the control leaves the method. Also, every time you call the method another variable, accessible by the same local name is created on the stack.
You can't have truly "global" variables in Java the same way as you can in a language such as C. Java forces you to structure your program in an object oriented way.
In your example above, if var is required throughout a whole test object and is important to have stored, then you would use the first example. If var is only required in someMethod and it's not important for a test object to store it then use the second example.
Take note that even with the first example, var is encapsulated within a test object, so it's not really "global" at all, apart from maybe slightly to the member function of test (which is the whole point of instance/member variables).
The closest thing in Java to "global" data is something like:
public class GlobalVars {
public static int globalInt;
}
And you could access globalInt throughout your code as GlobalVars.globalInt, without creating an instance of GlobalVars.
I have the following code:
public class BookLib {
void f() {
final int x = 5; // Line 1
class MyCLass {
void print() {
System.out.println(x);
}
}
}
}
I don't understand why should use final variable in this case (Line 1)?
You've created an inner class here. Since the life-time of objects of this class can potentially be much greater than the runtime of the method invocation (i.e. the object can still exist long after the method has returned), it needs to "preserve" the state of local variables that it can access.
This preserving is done by creating an (invisible, synthetic) copy inside the inner class and automatically replacing all references to the local variable with references to that copy. This could lead to strange effects when the local variable were modified after the inner class object was created.
To avoid this, there is a requirement that all local variables that you access this way are final: this ensures that there is only ever one possible value for the local variable and no inconsistencies are observed.
This specific rule can be found in §8.1.3 Inner Classes and Enclosing Instances of the JLS:
Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final. Any local variable, used but not declared in an inner class must be definitely assigned (§16) before the body of the inner class.
Here you create an inner class. In order to access the context of execution, the references to the variables should stay intact, otherwise an error behaviour is observed. In order to guarantee this, you should declare your variable final: thus one can't change it.
See detailed explanation here.
From kathy sierra scjp Book
The local variables of the method live on the stack, and exist only for the lifetime of the method. We already know that the scope of a local variable is limited to the method the variable is declared in. When the method ends, the stack frame is blown away and the variable is history. But even after the method completes, the inner class object created within it might still be alive on the heap if, for example, a reference to it was passed into some other code and then stored in an instance variable. Because the local variables aren't guaranteed to be alive as long as the method-local inner class object, the inner class object can't use them. Unless the local variables are marked final!
So you have a local final variable and method-local inner class. A method-local inner class cannot use non-final variables declared within method (including parameters).
To go more deeply into this:
Method-local inner class can be instantiated only within method where the class is defined. The local variables live on stack for the lifetime of the method. As the method ends, the local variables disappear, however the inner class object created still lives.
It's a matter of lifetime/scope.