I was asked this question in one of the tests:
class A{
int i;
public A(int x){this.i = x;}
}
class B extends A{
int j;
public B(int x, int y){
super(x);
this.j = y;
}
}
Given the following code, which of the constructors shown in the options can be added to class B without causing compilation to fail?
Options:
B() {}
B(int y){ j = y; }
B(int y) { super(y*2); j=y; }
B(int y) { i=y; j=y*2; }
B(int z) { this(z,z); }
What should be the answer?
I tried searching for it but want to know the reasoning behind the correct answer.
I tried searching for it but want to know the reasoning behind the
correct answer.
From source one can read:
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
Let us go through each option one by one:
1- B() {} No, because class A does not have no default constructor;
2- B(int y){ j = y; }, No for the same reason a 1);
3- B(int y) { super(y*2); j=y; }. Valid, this one explicitly invokes super with a valid constructor;
4- B(int y) { i=y; j=y*2; } No, for the same reason as 1) and 2);
5- B(int z) { this(z,z); }. Valid, this one calls the constructor :
public B(int x, int y){
super(x);
this.j = y;
}
which explicitly invokes super with a valid constructor.
If class A was instead :
class A{
int i;
public A(){}
public A(int x){this.i = x;}
}
because now class A has explicitly the default constructor all options would be valid.
Related
I've been reading about instance initializers in Java, and it's been explained that code common to all constructors can be put into them because they are called every time a new instance of a class is created. Is there an equivalent of instance initializers that run after constructors, for code that would be common to all constructors, but depends on what happens in the constructors?
No, there isn't an exact equivalent. If you want to run some common code, you can always factor out a method and call it at the end of all your constructors:
public class C {
private int x = 5;
private String y;
public C(int x) {
this.x = x;
endConstructor();
}
public C(String x) {
this.x = x.length;
endConstructor();
}
private void endConstructor() {
y = x + "!";
}
}
Sometimes, what seems like a situation where you want to call the same code at the "end" of all constructors can be refactored so that this code is in a single main constructor. Then, all other constructors call it using this(). For the example above:
public class C {
private int x = 5;
private String y;
public C(int x) {
this.x = x;
y = x + "!";
}
public C(String x) {
this(x.length);
}
}
The main constructor can be private, if appropriate.
Something like the #PostConstruct annotation can be used.
If your class has its dependencies injected using setter methods, then its constructor won't fully initialize an instance. Thus, additional "initializations" need to be performed after all the setter methods have been called.
If you think something happens in constructor:
class X {
private int x;
public X() {
// Code that sets x
// =-=-= HERE =-=-=
}
}
Insert the code you want to happen after the constructor... At the end of constructor.
If you have many constructors and don't want to duplicate code:
class X {
private int x;
public X() {
// Code that sets x
init();
}
public X(int x2) {
x = x2;
init();
}
private void init() {
// =-=-= HERE =-=-=
}
}
If every constructor invokes init, we may say this is invoked as a part of constructor, not after it. Imagine a train with one additional car following it, 50cm from it. Both have the same destination/time. Why couldn't we connect the train with standalone car?
Consider following class:
class Foo
{
private class Bar
{
int operatedNumber;
Bar(int x, int y)
{
operatedNumber = operate(x,y);
}
int operate(int x)
{
return x*2;
}
}
public int operate(int x, int y)
{
return x+y;
}
public Foo()
{
Bar b = new Bar(3,5);
}
}
I am getting compile time error The method operate() is not applicable for the arguments (int, int).
Is there a way to call the second operate() function?
Is there a way to call the second operate() function?
Yes - you can qualify it with Foo.this to refer to the enclosing instance of Foo:
operatedNumber = Foo.this.operate(x,y);
I have
class A {
int var;
public A(int x) {
var = x;
}
}
class B extends A {
int var2;
public B(int x, int y) {
super(...);
var2 = y;
x = f(y);
}
}
For the subclass B, I need to calculate the value x that is used in the constructor of A. If I were free to move super below my x=f(y) then I could pass in the result to the constructor of A (super). But super has to be the first line in the constructor of B.
Is there any way to initialize A with the proper value the first time? What if A.var were final and i couldn't go back and change it after construction?
Sure, I could put super(f(y)), but I could imagine cases where this would become difficult.
Assuming var is private and you need to set the value with the constructor (which seems to be the point of the question, otherwise there are many easy solutions), I would just do it with a static factory-like method.
class B extends A {
int var2;
public static B createB(int x, int y) {
x = f(y);
return new B(x, y);
}
public B(x, y) {
super(x);
this.var2 = y;
}
}
something like that. You have no choice, as explicit constructor invocation must happen on the first line of the wrapping constructor.
You can do it like this :
class B extends A {
int var2;
public B(int x, int y) {
super(calculateX(y));
var2 = y;
}
private static int calculateX(int y) {
return y;
}
}
Calling a static method is the only thing you can do before calling the superclass constructor.
Alternative to hvgotcodes, since it looks like you also want to set A's variable...
class B extends A {
int var2;
public B(int x, int y) {
super(x);
var2 = y;
x = f(y);
super.var = ...;
}
}
Another approach could be to add a protected constructor without parameters to A that relies on lazy initialization:
class A {
int var;
public A(int x) {
var = x;
}
/**
* Just use this constructor if you initialize var
*/
protected A(int x) {
}
}
class B extends A {
int var2;
public B(int x, int y) {
super();
var2 = y;
var = f(y);
}
}
But that's hard to document, not very obvious to team members and shouldn't be used for an api.
I'm a little curious about some of the code that I saw at school and whether or not this is common practice in the field or just bad design.
Consider the following interface and the two classes that implement it...
public abstract interface Anchor
{
public abstract double x(double x);
public abstract double y(double y);
}
Notice in the Cycle class the arguments in x() and y() are actually used...
public class Cycle implements Anchor
{
public Anchor anchor;
public double radius;
public double period;
public double phase = 4.0D;
public Cycle(Anchor anchor, double radius, double period) {
this.anchor = anchor;
this.radius = radius;
this.period = period;
}
public double angle(double day) {
return this.phase * 3.141592653589793D * (day / this.period) / 2.0D;
}
public double x(double x) {
return this.anchor.x(x) + Math.cos(angle(x)) * this.radius;
}
public double y(double y) {
return this.anchor.y(y) + Math.sin(angle(x)) * this.radius;
}
}
But here in the Center class the arguments in x() and y() exist solely to fulfill the contact with the Anchor interface and aren't actually used in the method...
public class Center implements Anchor
{
public double x;
public double y;
public Center(double x, double y) {
this.x = x;
this.y = y;
}
public double x(double x) { return this.x; }
public double y(double y) { return this.y; }
}
Is this something that you'll see commonly in production java code? Is it an accepted practice or a bad work around?
Yes, this is very common to all OOP code.
An interface defines a set of methods that are available on any objects that implement that interface. The implementation of those methods is something that a caller isn't supposed to care about, and it's not at all unusual that some arguments seen in an interface don't apply to certain implementations.
While adpalumbo is correct that it's not an unusual situation, it can also be indicative of a design problem, particularly if you have a long list of parameters and each implementation uses a different one. E.g.
interface Waffle {
void iron(int a, int b, int c, int d, int e);
}
class Belgian implements Waffle {
void iron(int a, int b, int c, int d, int e) {
doSomethingWith(a);
}
}
class American implements Waffle {
void iron(int a, int b, int c, int d, int e) {
doSomethingElseWith(b);
}
}
class Scandinavian implements Waffle {
void iron(int a, int b, int c, int d, int e) {
andYetAgainWith(c);
}
}
// etc.
I like waffles, but that's just nasty.
The real question is whether the arguments, taken as a whole, make sense in the context of whatever the interface is supposed to represent.
To add in to 2 posts above, I would like to point out following.
The use of abstract keyword in interface declaration is considered very bad practice as this is considered obsolete, because the interface is considered abstract implicitly.
The use of abstract keyword in method declaration in the interface is considered extremely bad practice for the same reason as pointed in point 1 above. Methods declarations are implicitly abstract.
The use of Public keyword in method declaration is also considered very bad practice for the same reason, as methods declared in interface are implicitly public.
The methods in interface can not be static as static methods can't be abstract.
I have a question similar to In Java, why can't I declare a final member (w/o initializing it) in the parent class and set its value in the subclass? How can I work around? but which requires a different solution. As in the above case, I want to declare a variable to be Final in the superclass, but I want the subclass to give it the value. What makes my problem different though is that I don't want the value passed in to the subclass, I want the subclass to 'know' its value, so the above solution doesn't work for me. Then I tried to do this:
public class Superclass{
public final int x;
public Superclass(int x){
this.x = x;
}
}
public class Subclass extends Superclass{
public Subclass(){
x = 1;
super(x);
}
}
...which didn't work (the call to super() must be on the first line :/ ). But this is basically the behavior that I want. Is there a good way to do this? Thanks!
You could do
super(1);
so instead of setting x, you are passing the value.
An alternative to the one above:
class Superclass{
public final int x;
public Superclass(int x){
this.x = x;
}
public static Superclass createNew(Integer y) {
return new Superclass(y);
}
public void print() {
System.out.println(this.x);
}
}
class Subclass extends Superclass{
public Subclass(int x) {
super(process(x));
}
public static Integer process(Integer y) {
if (y < 100)
y += 100;
return y;
}
}
I don't have a java compiler handy, but you're attempting to set x = 1 twice in this code.
x = 1;
And
super(x); //==> this.x = x
Do as #Kal said and do super(1), as x = 1 won't work.