0

I have a User (parent) with a Task (child). I need a user instance within each task and want to have the task available within the user.

Are there any differences in version 1 and 2?

Which version should I prefer?

Version 1:

public class User {

// does this creates a new Task on each field access?
private Task task = new Task(this);

public void runTask() {
   task.run();
}

}

Version 2:

public class User {

private Task task;

public getTask() {
   if(task == null) {
    task = new Task(this);
   }
   return task;
}

public void runTask() {
   task.run();
}
}

I guess, the first version does an eager initializing and is the same as doing this:

Version 3

public class User {
    public User(){
       // I need the user instance to put into the task, but this is null here..
       this.task = new Task(this);
    } 
    private Task task;

}

What I want to achieve is:

I have a lot of methods within User.java and want to outsource these methods to a new class Task.java (with the relation to its user).

nimo23
  • 5,170
  • 10
  • 46
  • 75

3 Answers3

0

Version 2 could lead to a NullPointerException, due to you always must call getTask() before runTask() otherwise NullPointerExceptionwill be thrown.

You could create the Task instance just before run it

public class User {

    private Task task;

    public void runTask() {

        if (task == null) {
            task = new Task(this);
        }

        task.run();
    }
}
eHayik
  • 2,981
  • 1
  • 21
  • 33
  • No I want to have the task instance access globally to the User-instance.. – nimo23 Oct 28 '19 at 09:48
  • @nimo23 what do you mean? Are you sure you don't want an inner class here? – Federico klez Culloca Oct 28 '19 at 09:49
  • An inner class (non-static nested class) would be perfect because I also need to access a lot of user properties/methods within the task object. However, I guess, it would be better to extract all this task-related props/methods into **an own file**, because the User.class is actually so large .. – nimo23 Oct 28 '19 at 09:54
  • It should be a bidirectional relationship between user and task. – nimo23 Oct 28 '19 at 09:58
  • Another approach could be creating an `UserTask.class` composed by `User` and `Task` objects – eHayik Oct 28 '19 at 09:58
0

Edit: Since your comment cleared some things up, here's the approach you should probably be taking:


public class User {

    private Task task;

    public User()
    {

    }

    public void runTask() 
    {
        if(task == null) 
        {
            task = new Task();
        }

        task.run();
    }
}

public class Task extends User { 
    public Task() 
    {

    }    
}

Like this, Task will inherit all methods and attributes from User. I'm not entirely sure how that effects the constructor of User, that depends on how exactly the rest of you class looks like. Now you can call Task with the same constructor as User and you can also define your own constructor in Task with the parameters of User constructor and additional parameters if needed.

yur
  • 380
  • 2
  • 15
  • And how should the task object access users methods? It should be a bidirectional relationship between user and task. – nimo23 Oct 28 '19 at 09:58
  • I see, so you want Task to be a subclass of User. You should read up on inheritance then: https://www.geeksforgeeks.org/inheritance-in-java/ – yur Oct 28 '19 at 10:00
  • 1
    ```public class Task extends User {} ``` – yur Oct 28 '19 at 10:01
  • The problem was that User is a JPA Entity class..extending task with user is not trivial with JPA..However, I found a solution with this: https://stackoverflow.com/questions/12570251/extend-jpa-entity-to-add-attributes-and-logic – nimo23 Oct 28 '19 at 10:18
0
 public class User {

// does this creates a new Task on each field access?
private Task task = new Task(this);

To answer the question in there: each time you create a new User object, the task field of that new user will be initialized. Only then. Once. If you want to ensure it doesn't get re-assigned, it might be beneficial to do:

private final Task task = new Task(this);

But the real problem here is different: you create a very strange dependency here. You already say that your User class has too many fields, and now you add another responsibility to it, namely to run "tasks".

Thus the real answer here: step back.

Get some more experienced people to sit down with you. Explain your requirements to them, and have them review your design and code base. There is no single "do this, not that" answer here.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • "you create a very strange dependency here"->a bidirectional relationship is not strange. – nimo23 Oct 28 '19 at 10:08
  • "User class has too many fields"->yes, and I want to outsource many fields and methods to another class (Task.java) and replaced those within User.java by only **one** field called task. – nimo23 Oct 28 '19 at 10:09
  • @nimo23 Unless you start violating things such as the "single responsibility principle". – GhostCat Oct 28 '19 at 10:10