Query about setname() method in Java - java

I am very new to java and I was just trying to get acclimatised to the syntax and there is one thing that I have been confused about. What is the difference between instantiating a new object in java then using the setname method to name it, and using a string parameter to assign a name in the constructor.
So if I have a class called Dog, what is the difference between,
naming the dog by passing a name parameter onto its constructor and using setname under it. Are these processes different.

Yes these are two differents things.
You have to think about what exactly is your object and how he relates to his properties.
Constructor let you initialize the class variables dynamically at the time of instantiating the class so you should put the parameters without which the object would not be what it is (In the context of your code)
The setters methods are a totally different thing, it let you access variable to modify it.
You should have setters when ,in your code, it make sense to modify a private variable.
If having a Dog without a name does not make sense in your code then add it as parameter in constructor.
Can a Dog be renamed ? if yes, then add a setName method.
Does your Dog have a default run speed that you can modify ? Then add a default speed variable in the class and setSpeed method.
Constructor are for parameters that make an object what it is and parameters that you always want to define when instanciating the object.
Setters are for modifying parameters after object was created.

Related

Is overriding toString() considered polymorphism?

I was having an exam in Java today and the examiner asked me if I can provide any examples of using polymorphism in my Spring Boot project.
As I couldn`t think of anything at first, he pointed out that I have overriden toString() in my models and that this is dynamic/runtime polymorphism.
However, I am not sure that I understand his point, because to my understanding, a behavior is considered polymorphmic when we have a parent class reference variable pointing to a subclass object (focusing on dynamic polymorphism).
Then at runtime the actual object, to which the parent class variable points to, is fetched and its method is called, as explained nicely here.
However, I do not use upcasting in my project (i.e. initializing my POJO classes with an Object class variable).
Thus, my question is - is overriding toString() considered polymorphism, although the parent class (Object) is never used as a reference variable?
All exampes of runtime polymorphism that I find on Stackoverflow, including the ones here and this one with toString, illustrate a situation where we have a parent class variable pointing to a subclass object, e.g:
Object object = new User("petar");
String name = object.toString(); // assign to variable for clarity`s sake
System.out.println(name);
// prints petar
Where my User class is:
public class User {
String name;
public User(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
However, in my project I simply create users and other POJO classes with their own reference variables, e.g:
User user = new User("petar");
String name = user.toString();
System.out.println(name);
// prints petar, as toString is overriden
Is the above considered polymorphism, although there is no upcasting / parent reference variable involved?
My classmate argues that it is, because for non-final instance methods, the compiler doesn`t know which method to call - it only ensures that there is such method in the superclass, so it prolongs this decision up until runtime (late binding) by inserting an instruction into the compiled code, which is checked then and the actual object, to which the variable points to, is fetched, and its method is called (source).
However, in this article it is stated that:
Method Overriding is an example of runtime polymorphism. When a parent
class reference points to the child class object then the call to the
overridden method is determined at runtime, because during method call
which method(parent class or child class) is to be executed is
determined by the type of object. This process in which call to the
overridden method is resolved at runtime is known as dynamic method
dispatch.
So: is method overriding sufficient for polymorphism, or is it a requirement that there is a parent class reference to the subclass object? Am I safe to say at interviews that merely overriding toString() is an example of polymorphism?
Thanks to the comments and a few other sources, I believe I can now answer my question as follows:
One could argue that overriding toString() is an example of polymorphism because:
The Java Virtual Machine (JVM) always selects the method to invoke on non-final instance methods based on the object that it is referenced to, and not the method defined by the variable type. This is known as dynamic method invocation or late binding i.e - the decision which method to call happens at runtime, hence the wording "runtime" polymorphism. Source: Oracle Docs, JavaWorld.
Thus, regardless whether we consciously use polymorphism by e.g. programming to interfaces or we do a simple toString() method override, but still continue to use our classes with their own class variables (i.e. using a "User" variable instead of the parent class "Object" variable), a decision about which method to call is always made on runtime by checking the type of object our variables are referring to.
Thus, the evaluation on which model to call (i.e. the polimorphic behavior) happens, regardless which of the two initializations we use:
User user = new User("username1");
System.out.println(user);
// or
Object object = new User("username1");
System.out.println(object);
The type of the variable is insignificant for our question, what matters is the object that it is referring to, and which of all possible objects it refers to (i.e a parent or a child), is decided on runtime.
The type of the variable is only relevant to either limit the scope of available methods to the ones in the parent class and potentially overridden by its children (if we use a parent class reference variable) or to gain access to the specific methods of the child (if we use a child class reference variable).
For example, if we added a new method to our User class:
public String instanceMethod () {
return "User instance method called";
}
It would not be available through a Object class variable:
It would only be available through a User class variable.
Hope this clears the confusion for everyone else that needs a more detailed explanation too.

Why is the "this" keyword used in Constructor and Setters?

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.

What's the difference between constructors and passing parameters?

I believe I understand what constructors are now, but to me it seems they are just used for passing info to methods in another class. So why not just call a method and supply a parameter instead? Have I got this wrong?
Constructors are used to create objects and are not ordinary methods. Whenever you use new to create an object, you actually call a constructor. For example:
new MyClass(); //here MyClass() is a constructor with no params
Note:
Constructor declarations look like method declarations—except that
they use the name of the class and have no return type
If I understand it right:
Constructors are always called, so these attributes MUST BE passed. If you pass this info through methods they don't have to be passed, so they could be missing.
Constructors are used to initialize new instance of an object, whenever you pass parameters or not.
Having parameters in a constructor is just a way to make it easy to set some initial attributes during the object initialization, which the object will most probably need in order to work as expected.
However, if those attributes weren't needed to be initialized for the correct operation of the instance object, it would make more sense not to pass them to the constructor, but just having some setters to pass them at any other time you need.

constructor clarification

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.

Java Variables Conventions

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.

Categories