-3

Note well: The same question applies for other immutable types, like String and Boolean.


I have a method like this (this is a simple example of a more complicated method):

Example 1

public BigDecimal addTwo(BigDecimal bigDecimal) {
    bigDecimal = bigDecimal.add(new BigDecimal(2));
    return bigDecimal;
}

I know, I could simply return bigDecimal.add(new BigDecimal(2)). But it's only an example.

The problem with this code is that I can't add final to the method parameter and Eclipse bothers me. So I would write:

Example 2

public BigDecimal addTwo(final BigDecimal bigDecimal) {
    BigDecimal bigDecimalLocal = bigDecimal;
    bigDecimalLocal = bigDecimalLocal.add(new BigDecimal(2));
    return bigDecimalLocal;
}

I know, I can do directly BigDecimal bigDecimalLocal = bigDecimal.add(new BigDecimal(2)). But I repeat, this is only an example.

The question is: when I do:

BigDecimal bigDecimalLocal = bigDecimal;

I'm not creating a new BigDecimal. I'm assigning the same object to a different variable. I found on SO that a simple way to clone BigDecimal is:

Example 3

BigDecimal bigDecimalLocal = new BigDecimal(bigDecimal.toString());

The question is: since BigDecimal is immutable, is this really necessary? Can't I simple do as in example #2? I think the final keyword could not be invalidated in that way.

Community
  • 1
  • 1
Marco Sulla
  • 13,595
  • 12
  • 50
  • 83
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/193257/discussion-on-question-by-marco-sulla-is-it-lecit-to-define-final-an-immutable-p). – Samuel Liew May 13 '19 at 11:49
  • Regarding the title, by "lecit" do you mean permitted, allowed? If so, that should be "legitimate" (shortened form is "legit", but that's not a real word). – halfer Jun 24 '19 at 07:17

3 Answers3

1

Example 2 is fine, but you don't need local variables at all and I think they decrease the readability of the method. I would simply do

public BigDecimal addTwo(final BigDecimal bigDecimal) {
    return bigDecimal.add(BigDecimal.valueOf(2));
}

What if I want to add another BigDecimal"? I have to return bigDecimal.add(BigDecimal.valueOf(2).add(BigDecimal.valueOf(3))? I think it's not so readable.

If you're going to add two many times (or multiple constants), then it might make sense to extract constants as constants. Like,

private static final BigDecimal TWO = BigDecimal.valueOf(2);
private static final BigDecimal THREE = BigDecimal.valueOf(3);

public static BigDecimal addTwoAndThree(final BigDecimal bigDecimal) {
    return TWO.add(THREE).add(bigDecimal);
}
Elliott Frisch
  • 183,598
  • 16
  • 131
  • 226
  • I wrote in the question that, and that this is just an example. – Marco Sulla May 12 '19 at 17:29
  • @MarcoSulla *I wrote in the question that,* My answer is worry more about code readability, which is not in your question. – Elliott Frisch May 12 '19 at 17:53
  • What if I want to add another `BigDecimal`? I have to return `bigDecimal.add(BigDecimal.valueOf(2).add(BigDecimal.valueOf(3))`? I think it's not so readable. – Marco Sulla May 12 '19 at 17:55
  • @MarcoSulla `bigDecimal.add(BigDecimal.valueOf(2)).add(BigDecimal.valueOf(3))`, which is as readable as it gets. – luk2302 May 12 '19 at 18:02
  • IMHO it's more readable `bigDecimal = bigDecimal.add(BigDecimal.valueOf(2); bigDecimal = bigDecimal.add(BigDecimal.valueOf(3);` (imagine it with returns) – Marco Sulla May 12 '19 at 18:19
  • @MarcoSulla do you see the problem? "IMHO"..., Os everywhere. – luk2302 May 12 '19 at 18:23
0

It seems you don't understand the concept of references.

When you have this:

BigDecimal incoming = new BigDecimal(2);
addTwo(incoming);
...

public BigDecimal addTwo(BigDecimal bigDecimal) {
  bigDecimal = bigDecimal.add(new BigDecimal(2));
}

Thing is: incoming is still 2 after that method ended!

That add() call creates a new BigDecimal object, and the variable bigDecimal points then to that new object.

But the reference incoming still points to the old object!

Long story short: that keyword final for method parameter does not at all what you think it does. Its sole purpose is to prevent you from re-assigning to that parameter/value. So you really want to learn about the difference between objects and references. And then about pass by reference.

GhostCat
  • 127,190
  • 21
  • 146
  • 218
  • The problem is I ***can't*** add the `final` keyword in that way to the parameter of `addTwo()`. Or are you saying is useless to add it in this case? – Marco Sulla May 12 '19 at 17:24
0

Well, I admit my ignorance about the final keyword. I must say I don't get its usefulness:

  • If you reassign a parameter inside the method, final or not, the object remains unchanged, of course

  • If you instead modify a non immutable object, final or not, the object changes also outside the method.

  • It seems the only thing that a parameter with final do is that it can't be reassigned within the method only.

I must say I do something like this a lot of time:

public List<MyBean> findByNation(String nation) {
    if (nation != null) {
        nation = nation.toUpperCase();
    } else {
        nation = "";
    }

    [...]
}

or

public List<Date> findConfirmedDates(Date start, Date end) {
    if (end == null) {
        end = new Date();
    }
}

or

public String findFilteredSql(String queryFilter, SearchBean searchBean) {
    if (searchBean.getSupplierId() != null) {
        queryFilter += " JOIN SUPPLIER_COMMODITY sc ON sc.SUPPLIERID = v.SUPPLIERID ";
    }

    [...]
}

or

public static String format(BigDecimal val, Locale locale, int scale) {
    if (val == null) {
        return "-";
    }

    val = valLocal.subtract(BigDecimal.ONE);
    val = val.multiply(NumberUtility.BigDecimal100);

    [...]
}

Yes, at university I learned that if I create a new variable, instead of overwriting the old one, the speed of the program is improved (I don't remember well, it seems to me that CPU and registers are involved in some way...). Anyway this is micro-optimizations, useful for C or Fortran libraries that do numeric computations.

IMHO it's much more readable the way I wrote the methods above, and sorry for final.

So I don't find the utility of final in these cases. Moreover, I don't find it's usefulness at all. I think I'll adopt the Example #1 in the question, and I'll simply disable the warning of Eclipse and do not add this keyword with arguably usefulness.

Marco Sulla
  • 13,595
  • 12
  • 50
  • 83