Java subclass constructors not calling parent class constructor - java

I ran into a weird situation the other day. Here it is:
I had an abstract class and a child class extending it. The abstract class had a no parameter constructor to initialize a map, but that's it.
The sub-class didn't have any constructors that I explicitly wrote, and everything worked fine.
Then one day I added a custom constructor in the subclass with a bunch of parameters for a unit test. This broke my main program, however, because the map in its parent class was always null.
To solve it, I put another constructor in the subclass that was totally blank (no params or anything). This for some reason assured that the super class constructor would be called and no null pointer exception thrown. Why was that not getting called before and why is it working now?
Subclass:
public class BillToSite extends XWStoreRequestDataElement {
private String country;
private String state;
private String county;
private String city;
private String zip;
private String address;
public BillToSite() { } //WHY DOES THIS FIX IT???
//Only used for unit test.
public BillToSite(String address, String city, String state, String zip, String county, String country){
this.address = address;
this.city = city;
this.state = state;
this.zip = zip;
this.county = county;
this.country = country;
}
Abstract class:
public abstract class XWStoreRequestDataElement {
private Map<String, String> attributes;
public XWStoreRequestDataElement(){
attributes = new HashMap<>();
}

I cannot explain why you experience BillToSite instances with attributes=null. That contradicts the way Java works. But I can explain why you have to write the no-args constructor.
Necessity of explicit no-args constructor
I suppose that in your program BillToSite instances are created using new BillToSite(), either explicitly or by some framework... (otherwise the class wouldn't have any instances).
In the original BillToSite.java you had no explicit constructor, so the Java compiler created one for you, effectively identical to the one you asked about.
Introducing the 6-args constructor deactivated the compiler's auto-creation of the no-args constructor, and as your code relies on this constructor, it's clear to me that it couldn't work any longer. Normally, you should have got compile errors for the new BillToSite() calls. If you didn't get them, I'd guess that the instance creation happens in some hidden place using reflection.
So, when you wrote the explicit no-args constructor, you re-introduced the missing element that was no longer auto-generated.
Calling the super constructor
You never need to explicitly begin a constructor with super() (we may regard it bad style if you omit it, thus not making clear which superclass constructor is to be used). If you don't explicitly call a super(...) or this(...) constructor, the compiler effectively inserts super() at the very beginning. In this regard, some of the other answers are misleading.
So adding that line to your BillToSite(...) constructors can't change anything.
I'd recommend that you run your program under debugger control with a breakpoint on the BillToSite() constructor and watch the attributes field. I'm sure it will be initialized to an empty HashSet. If you later experience a null value, the problem must be in another part of your code.

Simply call super(); in public BillToSite(){}
For example:
public BillToSite(String address, String city, String state, String zip, String county, String country){
super();
this.address = address;
this.city = city;
this.state = state;
this.zip = zip;
this.county = county;
this.country = country;
}

By default, Java provides a no-args constructor that makes a call to super() for any class that doesn't have any explicitly defined constructors. However, when you explicitly define a constructor, Java doesn't do that so you have to call super() yourself.
So, when you didn't have that subclass constructor, Java handled the no-args constructor for you, but when you added that subclass constructor, Java stopped handling that so you had to do it yourself. Another solution would to just explicitly call super() in your original subclass constructor instead of having a separate no-args constructor for it since all you really need to do is call super() to initialize the map.

Related

How do I interpret a getter method used as a parameter?

I have a bit of Java code that I can't follow. Two classes, ClassA and ClassB, structured like this:
ClassA {
void setName() {
this.name = name;
}
String getName() {
return name;
}
void writeFunction(Object value) {
String v = value.toString();
}
}
and
ClassB extends ClassA {
...
writeFunction( getName() );
...
}
I've never seen a getter method used without an object reference, so I'm not certain what's happening here. getName() can only refer to ClassA.getName(). My understanding is that methods can't be passed as parameters in Java, which means that the argument to writeFunction() must be the result of the method, presumably as this.getName?
Can anyone make an educated guess what's happening here? JavaBeans and JSP tag libraries are involved, if that means anything.
Edit: Added details to code
Calling an instance method from within the class that defines it calls it on the current instance (i.e. this). Here, you call getName() on the current ClassB object (the method is inherited from the super-class, ClassA), and then pass the returned value to writeObject.

Java setting the super extended class from the a passed in object

I have a class like this
public class User implements UserInterface, Parcelable
{
public User(int userID, String firstName, String lastName, String mobileNumber, Date dateAccountCreated)
{
this.userID = userID;
this.firstName = firstName;
this.lastName = lastName;
this.mobileNumber = mobileNumber;
this.dateAccountCreated = dateAccountCreated;
}
}
And I then have another class that extends into this:
public class Invitee extends User
{
private int eventDescision;
public Invitee(User u, int eventDescision)
{
super() = u;
this.eventDescision = eventDescision;
}
}
Obviously this line super() = u; does not work. However, how can I achieve the this functionality where I pass the User object the invitee recieves and set it as the extended object without having to create another constructor? I know I can just the object as a variable with a getter and setter, however, I like the way it flows without doing this as and invitee is always user.
User you receive in Invitee constructor is a real instance and you are creating another one. You can not assign one instance in a super constructor, you only can copy it, with a copy constructor.
It should rather be:
super(u.getUserID(),
u.getFirstName(),
u.getLastName(),
u.getMobileNumber(),
u.getDateAccountCreated());
You cannot automatically pass an instance of the base class to the base class' constructor call (super) in the child class' constructor.
What you might want to do is pass the base class' properties in the super call.
For instance is User properties are not private:
public Invitee(User u, int eventDescision) {
super(u.userID, u.firstName, u.lastName, u.mobileNumber, u.dateAccountCreated);
...
You can:
Use decorator design patter in Invitee
Define costructor User(User u)
as people manthioned before: use super() with all parameters
Remember that super is calling constructor of superclass, so you can't call constructor which is not defined.

Calling superclass from a subclass constructor in Java

I am trying to create a constructor that takes a field as a parameter, then puts it in a field that is stored in a superclass. Here is the code I am using
public crisps(String flavour, int quantity) {
this.flavour = super.getFlavour();
this.quantity = quantity;
}
In the superclass I have initialised the field with
private String flavour;
and I have an accessor method
public String getFlavour() {
return flavour;
}
I am getting an error "flavour has private access in the superclass", but I believe this shouldn't matter as I am calling the accessor method that returns it to the field?
What you should do:
Add a constructor to your super class:
public Superclass {
public SuperClass(String flavour) {
// super class constructor
this.flavour = flavour;
}
}
In the Crisps class:
public Crisps(String flavour, int quantity) {
super(flavour); // send flavour to the super class constructor
this.quantity = quantity;
}
Comments
Some comments to your question:
"In the superclass I have initialised the field with "
private String flavour;
This is not an initialization, it is a declaration. An initialization is when you set a value.
"I am getting an error " flavour has private access in the superclass" but I believe this shouldn't matter as I am calling the accessor method that returns it to the field?"
When you call a accessor (aka getter), it is ok - depends on the getter visibility.
The problem in you code is the:
this.flavour =
because flavour is not a field declared on Crisps class, but on the supper class, so you can't do a direct access like that. you should use my suggestion or declare a setter on the super class:
public void setFlavour(String flavour) {
this.flavour = flavour;
}
Then you can use it on the child class:
public Crisps(String flavour, int quantity) {
this.quantity = quantity;
super.setFlavour(flavour);
}
flavour is private. Although you're reading it from the public method, you're assigning it to a private field, and you likely didn't declare it in this class.
You could set flavour to protected in the parent class or define a setter for it
Ultimately your code doesn't really make sense though. Even if it did compile, it would be more or less: flavour = flavour. Perhaps you should rethink what you're trying to do a little bit
I think you may need a tighter grasp on Java and Object Oriented Programming.
http://docs.oracle.com/javase/tutorial/java/concepts/
You should start here.
public crisps(String flavour, int quantity)
{
super(flavour);
this.quantity = quantity;
}
This should work as see Docs
make
private String flavour;
public,otherwise your subclasses won't have access to this String.
Your superclass doesn't know about existence of any subclass. According to Java documentation, "private" makes any variable and method available within that class,where private variable or method was declared, no any class has access to it,even subclasses.
Once you chance your access modifier, you won't get any errors.

Java :Setter Getter and constructor

I'm a bit confused about the use of getter/setters and constructors (see the below code for an example)
public class ExampleClass {
private int value = 0;
public ExampleClass () {
value = 0;
}
public ExampleClass (int i) {
this.value = i;
}
public int getValue() {
return value;
}
public void setValue(int val) {
this.value = val;
}
public static void main(String[] args) {
ExampleClass example = new ExampleClass (20);
example.setValue(20);
//Both lines above do same thing - why use constructor?
System.out.println(example.getvalue());
}
}
All I've learned is that we need getters/setters for security and that they can also be used to change or edit values later on.
My question is that if the constructor is the point of initialization and a default constructor is always present, why use a constructor with parameters to initialize values instead of getters/setters?. Wouldn't using the getter and setter provide security as well being able to easily change values at any stage. Please clarify this point for me.
default constructor is always there
Well actually its not always there. A default constructor is the one which is provided by the compiler (of course it is a no-arg constructor ) Only if there is no other constructor defined in the class
why we use constructor with parameters to initialize values instead of set get
Because there could be a condition that an object can always be created only when all the values are provided at the time of initialization itself and there is no default value. So all values must be provided otherwise code will not compile.
Consider this Book class
public class Book {
private String title;
private String author;
public Book(String title, String author){
this.title = title;
this.author = author;
}
//getters and setters here
}
Consider a condition where a book can be created only if it has title and author.
You cannot do new Book() because no-arg constructor is absent and compiler will not provide one because one constructor is already defined.
Also you cannot do new Book() because our condition does not meet as every book requires a title and author.
This is the condition where parameterized constructor is useful.
Sometimes, when creating a new object of a class, some values HAVE TO be provided. For an example, when connecting to database and creating Connection class object you have to provide a connection string, so that it knows what are you connecting to. Creating new connection without specyfing target database would be pretty useless, right?
Also, take a look at this
Foo foo=new Foo(1,2,3,4,5,6,7);
and this
Foo foo=new Foo();
foo.setP1(1);
foo.setP2(2);
foo.setP3(3);
foo.setP4(4);
foo.setP5(5);
foo.setP6(6);
foo.setP7(7);
First one looks better, right?
My question is that if constructor is point of initialization and
default constructor is always there so why we use constructor with
parameters to initialize values instead of set get.
If you think about an object transitioning into different states then it makes sense to have a parameterized constructor alongwith setters and getters. Let me try to put a real life scenario: Think about an Employee class, a new employee joins, you don't know many details but few and you create the object of Employee with defualt and base value of its attributes. You need to register the employee in the system and hence you used the parameterized constructor. Once you get more details about the employee, you use getters and setters to update the attributes.
this is purely upto your coding style. But IMO, I would use parametrized constructor:
to initialize those values which should not be changed. (like username parameter for a person object)
to initialize those values, without setting which, the object will be in invalid state.
Say, you are sending login parameters to a method. You can use in these to ways
Login obj = new Login();
obj.setUsername("user");
obj.setPassword("pw")// what if someone commented this out, or you forget to call it
and otherway,
Login obj = new Login("user", "pw");
while you can send Login object just after setting username in 1st case, it would be invalid at recieving end. but the second method is less prone to bugs, bcz it becomes necessary to pass all the required parameters.
Just to make it easier. It takes less code to use a constructor than to create an object and use the setters.
Sometimes you don't need to set all the fields to specific values at the time of creating. For examle, when you make an array. Also, as already said, it's safer when you use getters -- you can't get nullpointer.
Remember to write the default constructor when you've defined constructor with parameters. Or be sure not to use it.
First, both methods: Constructor and Setter are safe ways to change object's attributes. Are expected from Class author to expose or not safe ways to modify an instance.
The default constructor is always provided if you have not written one:
// Example of a Class with a Default Constructor
public class GetSet {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static void main(String[] args) {
// Theres a implicit Default Constructor here
// Its ok to do that
// GetSet obj = new GetSet();
GetSet obj = new GetSet();
}
}
// Example of a Class without a Default Constructor
public class GetSet2 {
public GetSet2(String value) {
this.value = value;
}
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static void main(String[] args) {
// GetSet2 obj = new GetSet2(); // compile time error
// Default constructor is not provided, since u wrote one
}
}
2. About which is better: Using a constructor or via setter, it depends on what u want. If you will only modify an attribute of a existing object, u may use the setter, or for a completely filled object you may prefer the constructor instead.
// Example of modifing an obj via Setter and Constructor
public class GetSet3 {
public GetSet3(String value1, String value2, String value3, String value4) {
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
this.value4 = value4;
}
private String value1;
private String value2;
private String value3;
private String value4;
// ... Getters and Setters
public static void main(String[] args) {
// Its easier to this
GetSet3 obj;
obj= new GetSet3("j", "a", "v", "a");
// instead that
// its also easy to forget or do something wrong
// when u have a lot of attributes to set
obj.setValue1("j");
obj.setValue2("a");
obj.setValue3("v");
obj.setValue4("a");
}
}
It's easier and safer to initialize your object variables via your constructor to avoid nullpointers.
If you instantiate your object without initializing your variables first and you do a get operation on one of your null variables, you might get a nullpointer exception at runtime because you forgot to manually set its value.
On the flipside of that, if you always initialize your object variables in your default constructor, you have a seriously reduced risk of getting nullpointer exceptions during runtime because none of your variables can be null unless you specifically set them via a setter (which is not recommended).
Constructor with arguments makes you get the object fully constructed. If you want to use default one, you will have to make sure the fields are set using setters. During set of some property, assume the exception is thrown, now you have an object which is not usable. In several cases, setter wouldn't be exposed but getters. In those cases, having constructor with arguments or a named constructor is the right option. In a nutshell, getters and setters do have their own importance rather than initializing the object.
Why use getters and setters?
Because you write it using less, more elegant and better readable code when you set the values as parameters in a constructor. Moreover, sometimes some fields are indispensable for the object, so a parameter constructor prevents the user from creating an object omitting necessary fields for the object's functionality. One is though not "oblidged" to call the setters.
To answer this question, I say by writing getters/setters, we create a provision to add any validation method in the future, currently, there is no validation, but if anything goes wrong in the future we just add validation logic in the setter.
we can also write the logic/validation in constructors but it's not a good practice. The constructor should be used only to initialize your object's state/fields. You should delegate the responsibility of other things to other methods.
Note that a constructor is called only once i.e, whenever you create a new object With a sufficiently large input, you can cause an exception in your constructor.
This is one of several reasons why you should not use a constructor to contain "business logic".

Java - Setters from Constructors

package cen.col.course.demo;
import java.io.Serializable;
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
protected String code;
protected String title;
protected Professor professor;
public Course( String code) throws InvalidDataException {
super();
setCode(code);
}
public Course(String code, String title ) throws InvalidDataException {
this(code);
setTitle(title);
}
public Course(String code, String title, Professor professor) throws InvalidDataException {
this(code,title);
setProfessor(professor);
}
public String getCode() {
return code;
}
protected void setCode(String code) throws InvalidDataException {
if ( code == null || code.length() < 1) {
throw new InvalidDataException("Course must have a course code");
}
this.code = code;
}
public String getTitle() {
return title;
}
public void setTitle(String title) throws InvalidDataException {
if ( title == null || title.length() < 1) {
throw new InvalidDataException("Course must have a title");
}
this.title = title;
}
public Professor getProfessor() {
return professor;
}
public void setProfessor(Professor professor) {
this.professor = professor;
}
public String toString() {
String output = getCode() + ": [" + getTitle() + "]";
if (getProfessor() != null ) {
output += " is taught by " + getProfessor();
}
return output;
}
public boolean equals(Course c) {
if ( ! this.getCode().equals(c.getCode())){
return false;
}
if ( ! this.getTitle().equals(c.getTitle())){
return false;
}
// should the prof field be included in test for equality?
if ( ! this.getProfessor().equals(c.getProfessor())){
return false;
}
return true;
}
}
I have Three Questions:
I noticed my professor calling the setter methods from the constructors. I did a little searching around, and have mixed thoughts about it. Some say its okay, some say you have to be careful when your using subclasses, Is it okay to call your setters from the constructors?
The constructors throw exceptions because she is calling the setters from the constructor. Now my question is, if calling the setters from the constructors isn't a safe way of doing it, What is the proper way of doing it? My guess would be to declare a no argument constructor, and build the object using setters.
I guess doing this, is out of the question?
Course createCourse = new Course("1234","Programming 1","Pam Halpert");
I am calling the constructor that takes 3 arguments, However, if calling the setter from the constructor is not safe, how would go about doing this, and have the exception in place? Could I use if statements? Check to see if something is blank and throw the exception if necessary?
Calling the setters within the constructors generally has the advantage that sometimes setters already have some validation logic inside (like the setTitle in your example) and you don't want to duplicate this logic. However calling setters can lead to the problem, as you already mentioned, that subclasses may override them with unexpected behaviour. To solve this you can either make the setters private or final so that they can't get overriden. Calling only private/final setters is a good practice and should not lead to any problems.
It is fine that a constructor getting invalid data throws an exception. You do not want to create an invalid object.
It is rather bad practice to first create an empty object (through empty constructor) and then fill its data via setters. This way you will have for some time an object in a meaningless state which has some data filled, some data unfilled, and this might lead to troubles. Also, as another answer already mentioned you should think about reducing the numbers of constructors - is a Course without professor really valid? If not there doesn't need to be a constructor creating such an object...
Since this is homework, or some study, your professor prolly wanna show you things.
however ,
Course createCourse = new Course("1234","Programming 1","Pam Halpert");
is the best thing to do actually.
Depending on what you are developing, most of the time, you want to provide as little constructors as possible, unless you are designing a programming language. if you are working on a public API, or product, you should make sure that your consumers do not make mistakes, or abuse your API, if you allow them to create bugs.
Constructor can throw and exception, which is good.
As far as i see, calling the setter reason was doing some validation or some logic. which is fine.
Keep in mind, doing any work in constructor is considered a bad practice.
you should do it outside the class and pass them in as constructor arguments, or setter/getter.
Calling setters is useful if your setters do some form of data validation. This allows you to place the validation in a single place and ensure that properties that are set at the point of instantiation comply with validation rules.
However, the problem with this is that subclasses could override these setters, meaning that your expected validation no longer occurs.
As such, it makes sense to create private setters that do the validation. Call these private setters in your constructors. If you want to have public setters as well, that's fine, just create a public wrapper setter around your private setter.
Side Note:
Your professor's example is a little off.
The validation seems designed to ensure that title and code are always set. However, the code also provides constructors that allow you to not set a title. This is almost certainly a bug (I would certainly flag it as one in a code review).
Personally I am not a huge fan of setters. I like immutability so in your example I would pass in the parameters to the ctor. Do the checking there and then assign to final fields. Setters would not exist. You would only have getters.
If you want to update then you can introduce copy constructors.
Then you would know that the object when it is constructed is in a state that is valid. If some parts of it are null then you can overload the constructor. You do not know which fields need to be populated by having no-arg constrcturs and setters. By enforcing it with parameters in the constructor you are forcing the object to be initialised in a valid state.

Categories