Is it possible to pass a vector per parameter without instantiating it?

I wanted to pass a vetor (or a ArrayList) per parameter without instantiating it, but I'm pretty lost about that, because I usually instantiate an object list and I'll add the data in this list, but since I want to simply pass a single element to this list, I came up with the idea that it would be possible to pass this object list by parameter without instantiating it.

Constructor of my class:

public User(String email, String password, List<Role> roles) {
    this.password = password;
    this.email = email;
    this.roles = roles;
}

I tried instantiating my User object from following way:

User user = new User(
    email, 
    passwords, 
    new ArrayList<Role>(roleRepository.findByRole("USER"))
);

Without success, I tried creating another constructor:

 public User(String email, String password, Role[] roles) {
    this.password = password;
    this.email = email;
    AddNewRole(null, roles);
    this.recordLogSeparated = false;
}

And a method to pass the value to my list within my entity.

private void AddNewRole(Role role, Role [] roles ) {
    if (this.roles.isEmpty() )
        this.roles = new ArrayList<>();

    for (int i =0; i< roles.length; i++) {
        this.roles.add(roles[i]);
    }
}

Come On, Now I tried instantiating my object User as follows

User user = new User(
    email, 
    passwords, 
    [roleRepository.findByRole("USER"))]
);

Is there any alternative so that you don't need to run the alternatives below?

List<Role> roles = new ArrayList<Role>();
roles.add(roleRepositoryJPA.findByRole("USER"));

Or

Role roles [] = {roleRepositoryJPA.findByRole("USER")};
Author: hkotsubo, 2019-08-04

2 answers

If I understood your question Well, you want to pass straight A list of objects, I believe the code below works:

User user = new User(
email, 
passwords, 
Arrays.asList(roleRepository.findByRole("USER"))
);
 2
Author: G. Falcão, 2019-08-04 21:49:34

If you have a constructor that gets a list, there's no way to call it without having a list (unless you pass null, of course, but I don't think that's the purpose).

So the answer to " is it possible to pass a vector (or list) per parameter without instantiating it? " is not . Incidentally, if you need to pass any object as a parameter (assuming it won't pass null), you'll need to instantiate it at some point. There's no way to get away of that.

The answer you accepted uses Arrays.asList, and this method also instantiates a list . Just because you didn't instantiate the list directly doesn't mean it's not being instantiated elsewhere.

Actually the most you could do with Arrays.asList Was save a line or two of code (as you didn't have to create the list before). But you're still instantiating a list.

But okay, maybe what you meant is that only I wanted to save those lines even (without having to create the list directly), and have expressed itself badly by saying "without instantiating it", but it is good to make it clear that yes, the list is being instantiated (and sorry to be so repetitive, but I found it important to emphasize this...)


Has another detail: Arrays.asList returns an immutable "more or less" list. So if you try to add elements in the list, it will give error. For example, if the Class User has a method for add another Role:

public class User {

    public User(String email, String password, List<Role> roles) {
        this.password = password;
        this.email = email;
        this.roles = roles;
    }

    public void addRole(Role role) {
        this.roles.add(role);
    }
}

...

User user = new User(email, password, Arrays.asList(role1));
user.addRole(role2); // erro!

This code throws a UnsupportedOperationException, since the list returned by Arrays.asList does not allow new elements to be added (the same error occurs if you try to remove elements from the list). But as I said, the list returned by Arrays.asList is" more or less " immutable, since it allows an already existing element to be changed. For example:

public class User {
...
    public void mudaRole(Role role, int posicao) {
        this.roles.set(posicao, role);
    }
}

...

User user = new User(email, password, Arrays.asList(role1));
user.mudaRole(role2, 0); // muda a Role da posição 0 da lista

In this case the code works, because the list returned by Arrays.asList allows you to change the element in a position already available.

Depending on how you handle the list of roles, this may or may not make a difference. So it's important to know the implication of each method you use, and not use it simply to "save a line of code". a smaller code is not necessarily"better" .


Alternative: varargs

An alternative to "save rows" is to use varargs:

public User(String email, String password, Role... roles) {
    this.password = password;
    this.email = email;
    this.roles = Arrays.asList(roles);
}

...
// pode passar uma Role
User user = new User(email, password, role1);

// ou pode passar várias de uma vez
User user = new User(email, password, role1, role2, role3);

A syntax Role... roles indicates that you can pass one or more roles (or none, in which case the list will be empty).

Internally, the JVM "converts" these parameters to an array of Role, so it is still necessary to convert it to a list. I used Arrays.asList, but you could create it another way if you wanted to. For example:

this.roles = new ArrayList<>(Arrays.asList(roles));

This case is a little different: I create a list with all the roles (using Arrays.asList), and I create a ArrayList containing the elements of this list. To difference here is that this list is not "half immutable" as it happens if I just call Arrays.asList (with the ArrayList I can add and remove elements).

Also, with varargs you hide the internal implementation of the class : whether the roles are in a list, an array or any other internal structure, this is detail of implementation of the Class User; whoever creates the user only needs to pass the roles that he has, without needing to know if class it will create a list or not (and if one day this internal implementation changes, the other classes do not need to know, as the constructor will continue to receive the roles in the same way).

But of course, if the roles are in a list, then you will still continue instantiating a list (whoever creates User does not need to, it is just passing the roles to the constructor, but inside the Class User has an instance being created). I guess I said You can't escape that, right?

 7
Author: hkotsubo, 2019-08-05 01:55:05