A constructor is used to initialize a value and assign it to the class variable in the time of creating the class instance, right?
public class Joke{
private String jokeSetup;
private String jokePunchLine;
public Joke(String jokeSetup , String jokePunchLine){
this.jokeSetup=jokeSetup;
this.jokePunchLine=jokePunchLine;
}
}
Consider the following:
public Joke(String jokeSetup , String jokePunchLine)
Is another variable with same name created?
If so, why are they assigned to the former jokeSetup and jokePunchLine values?
PS:This code is not created by me.It was shown in the videos from which I am learning Java.
The purpose of a constructor is to initialize the object that was just created, for instance by filling in its instance fields (also called instance variables). this is used in your constructor to refer to the instance the constructor is initializing.
In your example constructor, you have parameters and instance fields. The constructor is taking the values of the parameters and assigning those values to the instance fields:
public Joke(String jokeSetup , String jokePunchLine)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---- Declares parameters this
// constructor accepts when
// called
{
// vvvvvvvvv------------ parameter
this.jokeSetup=jokeSetup;
// ^^^^^^^^^^^^^^---------------------- instance field
// vvvvvvvvvvvvv---- parameter
this.jokePunchLine=jokePunchLine;
// ^^^^^^^^^^^^^^^^^^------------------ instance field
}
The constructor could initialize instance fields with constant values instead, or by using a parameter value indirectly (for instance, looking something up), etc. It's not always a direct one-to-one assignment as it is in your example.
In your example, the parameters have the same names as the instance fields, but that's not a requirement. For instance, this constructor does exactly the same thing as yours:
public Joke(String theJokeSetup , String theJokePunchLine)
// ^---------------------^---------- Note the name changes
{
// vvvvvvvvvvvv------------ parameter
this.jokeSetup = theJokeSetup;
// ^^^^^^^^^^^^^^--------------------------- instance field
// vvvvvvvvvvvvvvvv---- parameter
this.jokePunchLine = theJokePunchLine;
// ^^^^^^^^^^^^^^^^^^----------------------- instance field
}
Java lets you leave off the this. part when referring to an instance field and just use the field name on its own (e.g. jokeSetup instead of this.jokeSetup). You can't do that in your constructor unless you rename the parameters, though, because they have the same names as the instance fields, so jokeSetup in your constructor is the parameter, not the field. When there's a conflict like that, the most local identifier takes precedence (in your constructor, the parameter is the most local).
When there's no conflict, it's a matter of style whether you use the this. part or not. (I always use this., I find it clearer.) So for instance, here's another version of that constructor which does exactly the same thing as your original:
public Joke(String theJokeSetup , String theJokePunchLine)
// ^---------------------^---------- Note the name changes
{
// vvvvvvvvvvvv------------ parameter
jokeSetup = theJokeSetup;
// ^^^^^^^^^--------------------------- instance field
// vvvvvvvvvvvvvvvv---- parameter
jokePunchLine = theJokePunchLine;
// ^^^^^^^^^^^^^----------------------- instance field
}
I mention this because, again, when there's no conflict, it's a matter of style, and you'll see this style used sometimes.
The class has a field named jokeSetup.
The method has a parameter of the same name that shadows that field.
So in essence there are two variables with the same name.
Using this makes it possible to again differentiate the two different usages of the same name, as this.whatever always denotes the corresponding field.
And you nailed it: shadowing is actually not a good idea. But this "pattern" is actually very common in Java. You could avoid it by giving the parameter a different name, such as _jokeSetup, but deviating from common practices is also bad practice.
A parametrized constructor can be used to initialize value to the variables in the time of creating it. When the parameters and variable names are same then in this case to differentiate between both, we use this keyword. This keyworord always refer to local variable of the method or class.
Java has an implied context for symbol names; the class instance (ie this) for non-static contexts and the class (eg Joke) for static.
This lets you omit the context when there is no conflict for the symbol name. For example
public String getJokeSetup() {
return jokeSetup; // no "this." required, it's implied
}
When there is a conflict for the name such as the case with a method argument named the same as a field, you need to explicitly define the context, eg
public void setJokeSetup(final String jokeSetup) {
// you must prefix the field with "this." to differentiate it from the argument
this.jokeSetup = jokeSetup;
}
Finally, here's an example that avoids a symbol name conflict
public void setJokeSetup(final String js) {
jokeSetup = js;
}
It is fairly typical to name arguments the same as the fields they correspond to but you're certainly not constricted to such a convention.
Related
I want to know the difference between accessing parent class fields using this and super.
We have the following abstract class named ListItem which extends Node class.
public abstract class ListItem {
protected ListItem rightLink=null;
abstract ListItem next();
}
And the following code inside the Node class:
public class Node extends ListItem {
#Override
ListItem next() {
return this.rightLink;
}
But if we use the code super.rightLink, I do not get any error at compile time or runtime. I just want to know what is the difference between the both and is there a best practice to accomplish the task?
Explanation
It does not matter in this case, there is no difference.
The field is declared in the parent class. So technically super.rightLink would makes the most sense. However, super and this are only relevant for resolving ambiguous situations with variable shadowing.
The best in this case would be to leave out any prefix and just type rightLink. But this is a bit opinion-based.
Example
Suppose we have the following
public class Parent {
int variable = 1; // Field
}
public class Child extends Parent {
int variable = 2; // Field
public void foo() {
int variable = 3; // Local variable
System.out.println(variable); // 3
System.out.println(this.variable); // 2
System.out.println(super.variable); // 1
}
}
In-depth
So we have a situation with 3 different variables which all live in a different scope, but they have the same name. When you just type variable, Java will refer to the variable with the lowest scope. Which would be the local variable in the method.
If you want to access your field, you need to do this.variable. If you want to access the field of your parent, you need to do super.variable.
So again, we have three different variables here.
no prefix: lowest scope
this: field with lowest scope
super: field with lowest scope, starting from the direct parent
In your specific example, however, we have no name shadowing at all. There is only one variable with the name rightLink. So all three variants refer to the exact same variable.
The best in this case would be to use no prefix at all, just rightLink.
JLS
Let us see how the Java Language Specification defines this. and super..
For this., refer to JLS§15.8.3:
When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method or default method was invoked (§15.12), or to the object being constructed. The value denoted by this in a lambda body is the same as the value denoted by this in the surrounding context.
For super., refer to JLS§15.11.2:
The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.
Unless rightLink is marked as private, it will be accessible in all classes deriving from ListItem. Thus, call super.rightLing and this.rightLink will be equivalent.
Generally, super refers to base class and this refers to class you are in. Use them appropraitely.
It's commonly used when overriding methods, i.e.
#Override
public void DoSomething(){
// Execute base imlpementation of a method
super.DoSomething();
// some additional code to add extra functionality to base class
}
From the java tutorial I see that a class can have two different constructors with the distinction being the number of arguments provided in each constructor, they also give an example of the no constructor parameter. Based on that information and their example. I have written the class to get a better understanding. I also notice that the fields inside the no param constructor can be changed using getter and setter methods, so I do not see differences with a constructor that has parameters. I have read some question here but they don't address this.
My question: Are there specific cases where such constructor SHOULD be used, if yes what is the reasoning behind it and are there benefits?
public class Course {
int numberOfStudents;
String courseName;
String courseLecturer;
public Course() {
this.courseName = "Human Science";
this.courseLecturer = "Jane Doe";
this.numberOfStudents = 22;
}
public Course(String courseName, String courseLecturer, int numberOfStudents) {
this.courseName = courseName;
this.courseLecturer = courseLecturer;
this.numberOfStudents = numberOfStudents;
}
public String getCourseName() {
return this.courseName;
}
public void setCourseName(String courseName) {
courseName = this.courseName;
}
public static void main(String[] args) {
Course courseType2 = new Course("CIV4046F", "Obi", 45);
System.out.println(courseType2.getCourseName());
}
}
No, defining default constructors with "realistically looking" too-specialized magic values is not a good idea, it will only cause trouble later on during debugging ("What's wrong with out database, where did this Jane Doe come from?").
Overriding default constructor might make more sense when there are some "canonical default values". For example, if you were modeling fractions, then setting the numerator to 0 and denominator to 1 would give a nice default representation of a zero as a fraction.
the default parameter constructor is used when the user doesn't affect any value at the instantiation so there is default values that can be used instead of emptiness , and if there is parameters the class use the parameters affected by the user.
There is definitely a use case for a default constructor (the one with no arguments) when you want to provide default values for non-final attributes. However, your example is not the recommended approach to provide such defaults. Your attributes should be initialized in the constructor, otherwise you have go around the class to know where the values come from. This would be better
public class Course {
//You should also keep these private to avoid them being set outside of the class
int numberOfStudents;
String courseName;
String courseLecturer;
public Course() {
this.courseName = "Human Science";
this.courseLecturer = "Jane Doe";
this.numberOfStudents = 22;
}
}
Constructor execution results in creation of an object. Once an object is created the user code is not forced to set any parameter before using the object even though there may be setter methods available.
Parametrized constructor and setter methods.
Suppose there is a class Duck with a parameter height of type int. You may have a setter method to set the height. Now if an object of Duck is created user code may use this invalid object of Duck (of 0 height). Even though setter method is present but still user code is not enforced to set it before using the created object. To enforce creation of object with necessary life giving parameters Parameterized constructors are needed. The setter methods enables you to modify the states during run time of the application. Based on the modified states the behavior of object can also be modified so they have a different use case but parameterized constructor solves different purpose as I mentioned above.
Default constructor on the other hand provide the user to create the object with states set to default values (these defaults may be defined inside the class while fields declaration itself or in super class or in other constructors or methods invoked by no parameter constructor).
you're getting confused because your parameters have the same name as your fields.
your no-arg constructor is setting the fields to the values that they have already have been given, which isn't very useful - there's no point in doing this. your constructor with three args sets the fields to the values that you are passing in. so if you want to set the fields to values other than your defaults, you need to use the constructor with three args. otherwise a no-arg constructor will do (although it doesn't need to do anything).
note also in Java, if you don't provide a constructor, you get a no-arg constructor for free. but as soon as you write a constructor with arguments, you will have to write a no-arg constructor (if you want one).
Your default constructor have no effect on class variables.
Instead of initializing class variable where it is declared you should initialize in the default constructor.
One of the many reasons to override default constructor in java is you want to initialize some class level parameters which you are going to processes in different method and those parameter are must to initialize that class.. There are many example in java for these kind of non default constructors for example
BufferedReader br=new BufferedReader(fr)
Where fr is file reader object. If file stream is not passed to buffer reader you cannot use buffer reader class.
As we know Java is an object oriented language. Everything is objects in Java. We also know that objects have something (instance variables / fields) and do something (methods). Its safe that we change the state of instance variables using methods i.e; setters & getters. So in a constructor we initialize the instance variables. So in other words constructor is doing something for an object. So isn't it correct to presume that constructor is kind of a utility method just like a setter which sets value? The difference is in case of a setter even we have return type void and in constructor we don't have any return type. And setters can be called any number of times on an object but constructor can be called once in a lifetime of an object.
Can we say Contructors are Methods in Java?
If you're new to Java and trying to grasp the concept for the first time, you can think of constructors as factory methods. (Like in Python for instance where a constructor just a method called __init__.) You should however move on quickly and understand that there are many differences. To name a few:
A constructor does not have a return type.
It has special obligations when it comes to initializing final member variables (a method can't even assign to final members).
It's static in the sense that you can invoke it without a callee, but it's non-static in the sense that you have a this reference.
It's invoked with special keyword, new, and has a special bytecode, invokespecial, while instance methods are called by obj.method() which typically compiles to the invokevirtual bytecode.
It must invoke super constructors unless there's a no-arg constructor in super class.
They are never inherited and can not be overridden.
Directly from the JLS (Chapter 8)
A constructor is used in the creation of an object that is an instance of a class (§12.5, §15.9).
The SimpleTypeName in the ConstructorDeclarator must be the simple name of the class that contains the constructor declaration; otherwise a compile-time error occurs.
In all other respects, the constructor declaration looks just like a method declaration that has no result (§8.4.5).
Constructor declarations are not members. They are never inherited and therefore are not subject to hiding or overriding.
Constructor in Java
Java constructor is invoked at the time of object creation. It constructs the values i.e. provides data for the object that is why it is known as constructor.
The constructor actually returns the current class instance (You cannot use return type yet it returns a value).
There are basically two rules defined for the constructor.
1)Constructor name must be same as its class name
2)Constructor must have no explicit return type
Types of constructors
1)Default constructor (no-arg constructor)
class Bike1{
Bike1(){System.out.println("Bike is created");}
public static void main(String args[]){
Bike1 b=new Bike1();
}
}
2)Parameterized constructor
class Student4{
int id;
String name;
Student4(int i,String n){
id = i;
name = n;
}
void display(){System.out.println(id+" "+name);}
public static void main(String args[]){
Student4 s1 = new Student4(111,"Karan");
Student4 s2 = new Student4(222,"Aryan");
s1.display();
s2.display();
}
}
a constructor is used to initialize variables, it is not a method. you can however choose to create constructor, if you do not the JVM will create a default constructor.
Given this code:
public class Example
{
public Example(String name)
{
input = name;
}
public someMethod()
{
//some code
}
}
In java when you declare a new (object or instance) as such:
Example foo = new Example("jo");
what is actually happening here?
my question is:
is a new object being created with the parameter of the class constructor?
will the new object have all of the arguments of the constructor and data members within the braces?
Given your code that does not have a default constructor
the line Example foo = new Example(); will result in compilation error
The default constructor is defined by default unless you add another constructor with argument(s). In this case you have to explicitly define the default constructor otherwise you can only create instance with the constructor that takes argument(s)
This will not compile. Java will automatically define a constructor for you if you don't include one. It will not include parameters. So if you took the public Example piece out of your code, or added in a no argument constructor Java would compile it.
Your code won't compile as you created a constructor and then tried to instantiate an object of the class without giving it any attributes (causing a compile error).
Additionally, it is worth pointing out that your code wouldn't work anyway as the input you use isn't defined anywhere. It should be defined before the public Example like so:
String input;
If you did this and DIDN'T specify a constructor (i.e. let Java create it for you), Java would hold the value "null" for input.
Any instance variables that are declared public and belong to the class will be accessible by the object you create.
Edit: Now you have altered your code to include the passing of an argument, it will compile provided you declare the String input as in my answer in the class.
As Rohit said you will have a compiler error as no default ctor is specified.
However, assuming you did have a default ctor: what happens is the data members are created, that is, memory is allocated for each non static instance member.
If the class extends any class, the constructor (parent's ctor) should be invoked before the subclass's constructor body executes, and then the constructor body initializes data members using local variables or local variables that are passed as ctor arguments.
If the constructor body executes to a completion, that is no exceptions, it returns a reference to the newly created object.
So:
new creates the object and returns the reference of that object if everything went well.
Constructors only initialize data. Using data defined in the
constructor body, or from arguments supplied by the constructor
caller. Those arguments don't create an object, they supply data
that may be useful to an object.
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.