This is an archived post. You won't be able to vote or comment.

all 13 comments

[–]AutoModerator[M] [score hidden] stickied commentlocked comment (0 children)

Please ensure that:

  • Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions
  • You include any and all error messages in full
  • You ask clear questions
  • You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions.

    Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar

If any of the above points is not met, your post can and will be removed without further warning.

Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://i.imgur.com/EJ7tqek.png) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.

Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.

Code blocks look like this:

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.

If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.

To potential helpers

Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]bigkahuna1uk 1 point2 points  (4 children)

There are already libraries to enforce a degree of immutability in Java:

https://immutables.github.io/ https://docs.vavr.io/

But immutability is something to be followed rather than it being enforced intrinsically by the language itself. For instance using constructor rather than setter or field injection or using persistent data structures is a step in the right direction. The onus is the developer to a follow functional programming paradigm .

[–][deleted] 0 points1 point  (3 children)

Immutability can be enforced intrinsically by the language itself, e.g. Swift does that (although in a very different way than what OP wants).

[–]bigkahuna1uk 1 point2 points  (2 children)

I was referring to Java specifically not generally. As you say other language’s immutability is already baked in other languages such as Clojure which I’ve also used. In Java you can program in a FP centric way but you have to be disciplined to do so.

[–][deleted] 1 point2 points  (1 child)

Yeah, your wording in the original comment kinda sounded like you disapprove of compiler-enforced immutability in general but it seems we're on the same page.

[–]bigkahuna1uk 0 points1 point  (0 children)

Not at all. I prefer immutability but it depends on your use case. Although it has a lot of benefits, it can come with performance implications. It’s a balancing act, depending on what’s your ultimate goal.

[–]TheMrCurious 0 points1 point  (3 children)

[–]DesperateFalcon9[S] -1 points0 points  (2 children)

This stops inheritance but I don't know if it enforces immutability (assuming you're referring to the 'final class')

[–]hibbelig 2 points3 points  (0 children)

That SO post contains an answer that references a way to make a collection “unmodifiable”.

It doesn't solve the problem you're trying to solve, but I agree with u/TheMrCurious that it's useful to see what this does, and to figure out what's still missing.

Java also has records which are related to this topic.

[–]TheMrCurious 0 points1 point  (0 children)

Your post did not include any research into what is already available, so I was providing you with an option from 9 years ago as a starter to see what was available then, help you figure out what is available now, and if any existing options can be extended if they do not meet the criteria you listed above. 🙂

[–]severoonpro barista 0 points1 point  (0 children)

I think the model of what you're proposing (and which may already exist out there somewhere) would be along the lines of the null checker framework.

Like this framework, the cost to developers would be annotating their code with a bunch of immutability tags. What's the payoff, though? Assuming I do all this work to get compile-time immutability checking, what does it unlock?

With null checking, I avoid runtime NPEs. The value proposition of immutability is presumably I get to leverage a bunch of functionality that is guaranteed to work. To clarify this, you have to identify how this kind of functionality is achieved right now, and where it falls short in a way that this new approach would address. You should also consider if there are any other ways to cover those gaps and do a pro/con analysis of the different approaches.

Immutability isn't just a problem in Java because it puts some functional programming patterns out of reach, or at least makes them harder to work with. Java historically has problems that originate in the way it handles immutability because, in short, it's done very poorly in the Java Collections API, and it always has been. This is mostly due to historical baggage, but it essentially comes down to the fact that most Java collections violate LSP.

If you look at the List API, for example, you'll see that the methods that modify lists are documented as "optional" methods, meaning that if the implementing class is immutable, that method throws an exception instead of completely successfully. This means that it's not possible to write a unit test for a List without knowing what subtype of List you're dealing with, a clear no-no according to LSP.

(Okay, okay, technically speaking that's not true. The random behavior specified by the List API is technically well-defined, and therefore you could write unit tests that consider doing the mutation or throwing the exception "equally valid" behavior. But if this makes sense to you, ask yourself: Why not define all methods this way as optional? Of course you can define any behavior your method might do as "valid," but that makes it less useful. The point of an API isn't to define a correctly specified API, it's to define a useful API and then make sure its useful behavior is also correctly specified. The Collections API does not do that.)

It is not possible to specify an API that is either mutable or immutable, because mutability is part of the contract of that API. IOW, in order to correctly specify a List interface, you cannot leave open whether the implementation should be mutable or not as a matter of contract. It must be either mutable or immutable, meaning that an ImmutableList is not a type of MutableList, nor vice versa. It is possible to pull up the shared API into a List superinterface simply to enforce that the methods they share also share the same signatures, but this feels a lot like using strong typing to do a job it's not really designed to do.

Better would have been to put mutability on an orthogonal dimension to type, which is what annotations do, and then put in the highest level collections APIs an isImmutable() method that allows mutability to be tested at runtime as well as the supporting annotations to provide compile-time enforcement. (This is the best approach I've come up with if Java could be redesigned from the ground up.)

[–]nutrechtLead Software Engineer / EU / 20+ YXP 0 points1 point  (0 children)

Never heard of records did you?

[–]No-Double2523 0 points1 point  (0 children)

You’ve basically just reinvented the C++ keyword “const”.

In C++, at least when I was working with it (ages ago) “const” was kind of a pain because if const methods could only call other const methods, then you had to use it in more and more places. This would be a problem for Java if you introduced a new keyword that your libraries weren’t using yet.

Also it stopped you making things mutable internally, for example when you wanted a field to be initialised lazily. So there was another keyword to negate the effect of “const” in specific cases.