0

I know this is a basic question but i would like to know how to solve this:

In a class we have a constructor as below:

public class Constructor{

private String a;
private String b;
private String c;

public Constructor(String a){
this.a = a;
this.b = getB(a);
this.c = getC(a,b);
}

public String getB(String a){
return a.trim();
}

public String getC(String a, String b){
return a + b;
}

}

When line this.c = getC(a,b) is called b is still null, how can we achieve this style of constructor?

Thanks.

ProjH
  • 13
  • 4
  • "When line this.c = getC(a,b) is called a and b are both still null" they're only null if you pass in null as their values, e.g. `new Constructor(null, null)`. – Andy Turner Feb 05 '21 at 13:38
  • @AndyTurner Sorry i see what you mean i have made an edit to try to complicate the issue a little more – ProjH Feb 05 '21 at 13:40
  • @ProjH the question is how you are calling your constructor or methods ? – Sudhir Ojha Feb 05 '21 at 13:46
  • Your IDE will warn you about an "overridable method call in constructor" (or at least your IDE should). When, in a constructor, you call a method which can be overridden by subclasses, the subclass has access to a not fully constructed object. **Be advised!** (More [details here](https://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-constructors).) – MC Emperor Feb 05 '21 at 13:48
  • Thanks, so how would you rearrange this to ensure that b exists before you run getC(), Is this not possible in a constructor. Do i have to separate these? – ProjH Feb 05 '21 at 13:52
  • Why do you think that `b` is null when you call `getC(a,b)`? `b` is assigned in the line above so it cannot be null (since `a.trim()` can never return null). – Thomas Kläger Feb 05 '21 at 13:54
  • Thanks @ThomasKläger If getB() looped through 9000 strings to match a string then trim for example, i.e the basis is getB() took time to run, would getC() be called before getB() has finished and created b. in this case could we get Null. i.e is it bad design is there a better reliable way to achieve this. – ProjH Feb 05 '21 at 13:59
  • It doesn't matter how much time `getB()` needs. Constructors are executed strictly sequential, so `getC()` is **never** started before `getB()` returns. – Thomas Kläger Feb 05 '21 at 14:04
  • Thank you @ThomasKläger, OK so the design is not flawed, so somewhere along the line something must be returning a null value. This constructor is valid. – ProjH Feb 05 '21 at 14:11

2 Answers2

1

The only reason for b to be null in this case is that the getB method is returning null.

Maybe this code is based on some other real code that has some other behavior in it causing the null.

rascio
  • 8,968
  • 19
  • 68
  • 108
  • 1
    This is correct, i have followed the code and there is a bug returning Null. So for anyone that is unsure as i was, the constructor design is sound and as pointed out by @ThomasKlager Constructors are executed strictly sequential. – ProjH Feb 05 '21 at 14:37
0

Looking at the constructor you have wrote and according to what is called the "variables scope", the instance of "a" which you are passing to the methods "getB" and "getC" is NOT the class instance member, but it is the reference of variable "a" passed in input to the constructor, thus the class instance member "b" will be already initialized when the method "getC" is invoked.
Surely, if you pass a null value to the constructor (i.e. new Constructor(null);) you will always get a "NullPointerException", but if the variable "a" is NOT null, you will have eventually:

  • Instance class member "a" = reference of input variable "a"
  • Instance class member "b" = string returned by "a.trim() , where leading and trailing space will be cut.
  • Instance class member "c" = concatenation of "a" and "b"

Here is an example of what I said:

public class Constructor {

private final String a;
private final String b;
private final String c;

public Constructor(String a) {
    this.a = a;
    this.b = getB(a);
    this.c = getC(a, b);
}

public String getB(String a) {
    return a.trim();
}

public String getC(String a, String b) {
    return a + b;
}

public static void main(String[] args) {
    Constructor myConstructor = new Constructor(" Hello ");
    System.out.println(myConstructor.a);
    System.out.println(myConstructor.b);
    System.out.println(myConstructor.c);
    new Constructor(null);
}

}

The result will be:

 Hello 
Hello
 Hello Hello
Exception in thread "main" java.lang.NullPointerException
at Constructor.getB(Constructor.java:15)
at Constructor.(Constructor.java:10)
at Constructor.main(Constructor.java:27)

Marco Tizzano
  • 1,726
  • 1
  • 11
  • 18
  • Thank you @MarcoTizzano as i have mentioned above you are correct the constructor is sound i have followed the code and there is a bug returning Null. So for anyone that is unsure as i was, the constructor design is sound and as pointed out by Thomas Klager Constructors are executed strictly sequential. – ProjH Feb 05 '21 at 14:38