Can I call a method before a constructor - java

I know I can call static methods inside a constructor.
I have one contructor in one class which is calling another constructor through this(arguments).
Secondly that second constructor is calling super(arguments) calling super constructor.
I want to execute some code before these constructors execute. I cannot use a static block. Any ideas?

You can call static methods. I often do it like this:
public class MyClass extends SuperDuperClass {
public MyClass() {
this(convert("Foo!")); // convert will be executed
// other constructor is called
}
public MyClass(String arg) {
super(convert(arg)); // convert will be executed
// before superconstructor is called
}
private static String convert(String arg) {
return arg + "_modified";
}
}
Of course, we can't call instance methods or use non static fields.
(and, of course, this pattern requires a constructor on super that takes parameters)

The super() call has to be the first statement in a constructor, no exceptions apart from statics which you've already mentioned you can't use.
Even when you don't explicitly write a super() call at the start of your constructor, the compiler puts it in for you. It's always there!
Your best bet is to refactor your code so you don't feel the need to call anything before the super() call, but without seeing the code (or at least more context behind it) no-one can tell you how is best to do that!

You can't - the first thing java needs is a super.constructer call - written or not!

Use the factory pattern so you can do this:
public static MyObject newInstance() {
staticMethod();
return new MyObject();
}
Assuming the static method isn't supposed to actually change how the constructor behaves, that will literally call it before the constructor is executed.

You can do this, also without a static block:
public Main() {
System.out.println("Inside Constructor");
}
{
System.out.println("Before Constructor");
}
public void doTest() {
this.doTest();
}

Related

Check is instance method is called from a constructor

I would like to check, from an instance method of a non-final class, whether the constructors and initializers of that class and its chain of subclasses for the specific instance have already completed.
In the following example, I have a class Abstract, which can be used to implement an interface which allows listeners to be added (which, for simplicity, are just Runnable instances here) and which provides a method signalEvent() which calls all attached listeners.
abstract class Abstract {
protected final void signalEvent() {
// Check that constructs have run and call listeners.
}
public final void addListener(Runnable runnable) {
...
}
}
class Concrete extends Abstract {
Concrete() {
// Should not call signalEvent() here.
}
void somethingHappened() {
// May call signalEvent() here.
}
}
Now it is possible to call signalEvent() from within the subclass constructor, but there is no way that a listener has already been added by that time and the event would just be lost. In our code-base, once in a while, someone adds such a call and I would like to be able to catch such calls as early as possible (using an assert statement or similar).
Is it possible to check whether an instance method is being called, directly or indirectly, from the subclass constructor or initializer of the current instance or, alternatively, is it possible to check whether all constructors for an instance have been completed?
In short, there is no elegant Java mechanism that allows you to do that, but you may consider using a factory pattern. Instead of creating instances directly using new keyword, you could create a factory class, that takes care of creating the actual instance and invokes an additional "post-create" method, that lets the instance know it's been completely created.
If you're using some dependency injection like spring, you get that out of the box, but if not, a solution could look something like this:
interface PostConstruct { // the classes need to implement that
void postConstruct();
}
public class InstanceFactory {
public <T extends PostConstruct> T create(Class<T> clazz, Object... params) {
T instance = //create using reflection
instance.postConstruct();
return instance;
}
}
A solution to the problem to see if a method or code is being called from a constructor. The code below will print true and false respectivly but would be slow and not pretty at all.
I still believe it is not the right solution for the problem above. As Codbender said, better to check if a listener has been added or set a status variable which would be faster
Edit - fixed the issue that Codebender mentioned and also made sure to check back in the stack trace incase of being called a couple of methods deep
public class TestClass extends TestAbstract {
public TestClass() throws Exception {
submethod();
}
public void submethod() throws Exception {
System.out.println(isInConstructor());
}
public static void main(String[] args) throws Exception {
System.out.println(new TestClass().isInConstructor());
}
}
public class TestAbstract {
public boolean isInConstructor() throws Exception {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement element : elements) {
if (element.getMethodName().equals("<init>") &&
TestAbstract.class.isAssignableFrom(Class.forName(element.getClassName()))) {
return true;
}
}
return false;
}
}

Calling a function from a constructor

How can I have the Edit() method be called by default when I construct a Breuk object?
public class Breuk {
public Breuk() {//constructor
}
private static Breuk Edit (Breuk b){ //function
}
}
Every time a new Breuk object is created, the Edit() method is called by default since it is placed inside the constructor. As the method is static, it has to be called in a statically way, i.e. ClassName.staticMethod(). As the method expects a Breuk object as argument, you pass this reference to it, meaning the object that's being constructed.
By the way, all method names should be lowercase according to Java conventions. So, consider renaming Edit(...) to edit(...).
class Breuk {
int x;
int y;
public Breuk(int x, int y) {
Breuk.Edit(this);
}
private static void Edit(Breuk b){
//edits breuk
}
}
First of all, you should stick to Java naming conventions, which state that method names should be lowerCamelCase. So you should rename your Edit() method to edit().
If you want the edit() method to be called by default when constructing an instance of the Breuk class, you can use an initializer block.
Excerpt from the Java Tutorial:
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
For your example, you could try something like this:
public class Breuk {
{ // initializer block
Breuk.edit(this); // always called by default,
// no matter which constructor is used
}
public Breuk() { // no-args constructor
}
public Breuk(int a1, int a2) { // another constructor
}
private static Breuk edit(Breuk b) { // function
}
}
Here I'm assuming you want to pass the instance being constructed to the edit() method, that's why this is passed as an argument.
EDIT:
In case this assumption is true, I suggest you make the edit() method return void, as you can't assign an instance to this, since it's final (and it doesn't make any sense, either).
Just call the method from the end of your default constructor. There's no need to think about any "default" calling here. Just implement it.
public class Breuk {
public Breuk() {
// constructor
edit(this);
}
private static Breuk edit (Breuk b){
// class-level processing on any Breuk that is constructed
}
}

regarding static method in java

When studying the java programming language, I meet the following statement
I am confusing about the statement marked with yellow. Especially, what does instance method mean here? If there is an example to explain this point, then it would be much appreciated.
If I have a method:
public static void print(String line) {
System.out.println(line);
}
... and then remove the static keyword ...
public void print(String line) {
System.out.println(line);
}
... it is now an instance method, can no longer be invoked from the class, and must instead be invoked from an instance (hence the name).
e.g.,
MyClass.print(line);
vs.
new MyClass().print(line);
That's really it.
You can call static methods without needing to intantiate an object:
TestObject.staticMethodCall();
For non-static methods you need to create an instance to call a method on:
new TestObject().nonStaticMethodCall();
Consider following sequence.
Define Class X with static void foo() a static method
Define Class Y which calls X.foo() in its main method
Compile the two classes and (somehow) run it
Change X.foo() to be a instance method by removing the static qualifier
Compile only X, not Y
Run the Y class again and observe the error.
On the other hand, if you had changed the body of X.foo in certain ways without changing its static-ness then there would have been no error. For more, look up "binary compatibility"
First of all, you should understand the difference between the class method and the instance method. An example is shown below.
public Class Example{
public static void main(String[] args) {
Example.method1();//or you can use method1() directly here
Example A = new Example();
A.method2();
}
public static void method1(){
}
public void method2(){
}
}
method1 is the class method which you can take it as the method of the class. You can invoke it without initiating a object by new method. So you can invoke it in such way: Example.method1()
method2 is the instance method which requires you to invoke it by initiating the instance of an object, i.e. Example A = new Example(); A.method2();
Additional:
The error is due to the removal of the static modifier of an class method like method1. Then method1 becomes an instance method like method2 which you have to initiate an instance to call.

Java method call in constructor chaining

Is it possible to call a constructor with the result of a method from another constructor of the same class?
I want to be able to accept input in several forms, and have something like:
public class MyClass
{
public MyClass(int intInput)
{
...
}
public MyClass(String stringInput);
{
this(convertToInt(stringInput));
}
public int convertToInt(String aString)
{
return anInt;
}
}
When I try to compile this, I get
error: cannot reference this before supertype constructor has been called
refering to convertToInt.
You just need to make convertToInt static. Since it doesn't really rely on on anything in the class instance, it probably doesn't really belong on this class anyway.
Here's an example:
class MyClass {
public MyClass(String string) {
this(ComplicatedTypeConverter.fromString(string));
}
public MyClass(ComplicatedType myType) {
this.myType = myType;
}
}
class ComplicatedTypeConverter {
public static ComplicatedType fromString(String string) {
return something;
}
}
You have to do it this way because, behind the scenes, the super-constructor (in this case Object) needs to be called before your own constructor is run. By referring to this (via the method call) before that invisible call to super(); happens you're violating a language constraint.
See the JLS section 8.8.7 and more of the JLS section 12.5.
The method convertToInt can't be called, because it needs to be run by an object, not just from a class. Therefore, changing the code to
public static int convertToInt(String aString)
{
return anInt;
}
means that convertToInt before the constructor has finished.
No its not possible. To call instance method all your super class constructor must have been called. In this case you are calling this() which replaces call to super(). You can not have both super() and this() in the same function either. So super class instance is not initialized in your case hence you are getting this error.
You can call like this
public MyClass(String stringInput) {
super(); // No need to even call... added just for clarification
int i = convertToInt(stringInput);
}
Making the method static might solve your problem.

Java passing subclass instance data to superclass constructors

Does anybody know if there's a way in Java to set the value of an instance variable in a subclass before calling the superclass constructor. I have a brief schematic below of what I'm trying to accomplish -- I need to set up the instance variables defined in the superclass differently depending on the subclass type, but I still want to be able to share common non-constructor code among different instances of the subclass.
Is there any clean way to do this, maybe some sort of coding pattern that I'm missing or something? Thanks in advance for any ideas.
public abstract class ConstraintSatisfactionProblem {
final Set<Variable> variables;
final Set<Constraint> constraints;
public Foo() {
this.variables = setupVariables();
this.constraints = setupConstraints();
}
public abstract Set<Variable> setupVariables();
public abstract Set<Constraint> setupConstraints();
public Map<Variable, Constraint> solve() { ... }
}
public class WordSquare extends ConstraintSatisfactionProblem {
final int size;
final static Set<Character> domain = ...;
public WordSquare() {
super(); // can I simulate calling super() after setting this.value = 4?
this.value = 4;
}
public Set<Variable> setupVariables() {
this.variables = new HashSet<Variable>();
for(int row = 0; row < size; ++row) {
for(int col = 0; col < size; ++col) {
variables.add(new Variable<Pair, Character>(new Pair(row, col), domain);
}
}
return this.variables;
}
public Set<Constraint> setupConstraints() {
// setup code specific to this problem
}
}
public class Cryptarithmetic extends ConstraintSatisfactionProblem {
final String problem;
public Cryptarithmetic(String problem) {
super();
this.problem = problem;
}
public Set<Variable> setupVariables() {
this.variables = new HashSet<Variable>();
for(char c : problem.toCharArray()) {
variables.add(new Variable<Character, Integer>(c, getDomain());
}
}
return this.variables;
}
public Set<Constraint> setupConstraints() {
// setup code specific to this problem
}
}
Firstly, please don't.
Secondly, really it's a really bad idea. Don't. Think about what you are trying to do in a broader context.
If you absolutely must do, you can stash it in a ThreadLocal. You can call a (non-instance) method by evaluating an expression the result of which is passed to a super() or this() (possibly the only reason why you need a second, private constructor that possibly takes a Void (capital 'V') argument). It's so evil, I am not going to even write the code down.
In your edited example code, just pass the sets into a protected constructor. If you have many arguments possibly some subclasses being special about some arguments, you might want to wrap all the arguments into a single argument object.
There is another really hacky approach, so long as you have -target 1.4 or later (which you should do!). Make the subclass an inner class (possibly anonymous). The references to the outer this and other captured variables are available before calling the super constructor.
public class Outer {
// What a hack!
private static abstract class Base {
Base() {
hello(); // Calling a virtual method in a constructor - poor form.
}
abstract void hello();
}
public static void main(String[] args) {
// Do not do this.
final String hi = "Hi!";
new Base() {
void hello() {
// Really, don't do it.
System.err.println(hi);
}
};
}
}
Place the common code you want to run in a protected method instead of in the constructor. Call that method when you wish.
You should never call any "alien" method (ie. overridable method of this class, or any method from any other class) form within a constructor. As long as the object is not fully initialized, you may have side-effects like the one you see.
In your case, in the subclass constructor, super() is called even before the "value" is set to 4. This means, the superclass constructor is called, then calls the "setup" method, while the "value" is still at 0.
Only once the superclass constructor returns, the "value" is set to 4. And it's too late then.
What I would recommend, is to set the "o1" variable to protected, so that subclasses can set its value themselves.
In Java, if you want to call a base class's constructor, you have to do it on the first line of your sub-class's constructor. So the answer is no, you can't set this.value before calling the super class's constructor.
But your sub-class's setup() method is already called in the super's constructor. Why don't you set your value there?
UPDATE:
Sorry, I didn't pay attention that your 'setup()' method returns a value. What you could do is make an abstract init() method in your super class, and call it in your super constructor before you call the setup() method. This way sub-classes will be forced to implement init(), and you would know that that is the place to initialize any sub-class's members before they are used in your super-class.
That being said, this approach does not force safety on you. When you call the super constructor from your sub-constructor, the sub-class instance is just starting to get created. It still needs to run the rest of the code in the sub-constructor before the object is safely created.
And in this situation, the super-constructor goes and calls the init() method on your just-in-the-process-of-creation sub-class. This means that if you go with approach, you have to be extra careful about what you do in the init() class.
Like others have said, don't do this. If you want to share some code between these classes, try containment/encapsulation instead of inheritance.
public class Foo {
private final Object o1;
public Foo(Object o) {
o1 = o;
}
public void complexMethodCommonToAllSubclassesOfFoo() { ... }
}
public class Bar {
private final int value;
private final Foo foo;
public Bar() {
super();
this.value = 4;
this.foo = new Foo( new Object() ); // or whatever
}
// If you need to expose complexMethodCommonToAllSubclassesOfFoo to clients of this class, just add the method and delegate to foo like this
public void complexMethodCommonToAllSubclassesOfFoo() {
foo.complexMethodCommonToAllSubclassesOfFoo();
}
}
I need to set up the instance variables defined in the superclass differently depending on the subclass type, but I still want to be able to share common non-constructor code among different instances of the subclass.
In that case, create a protected constructor in the superclass, and pass all of the customized values to it when you construct the subclass.

Categories