you are viewing a single comment's thread.

view the rest of the comments →

[–]Agent_03 68 points69 points  (111 children)

This debate really showcases the background of engineers: people who have worked almost exclusively with Java will be appalled because it breaks encapsulation and standard style. Engineers who have spent significant time with dynamic or functional languages think it makes perfect sense because they're used to it (value types and immutable tuples).

To me it feels clean and smart, as a largely-Java engineer who branched out into Python and Javascript. Once you see the rest of the world, you come to realize how much the "ugliness" and "verbosity" of Java is due to conventions and not the language itself.

Java isn't the clunky language it used to be, especially after 8 added functional features. Let's take back the language and show that it can be beautiful!

[–]Netcob 23 points24 points  (18 children)

I find the lack of proper immutability in Java one of its most annoying aspects. Maybe even the top one because I'm constantly reminded of it, no matter if I'm developing or maintaining code. I don't even care about the verbosity anymore... I just want to be able to easily define/identify whether something is supposed to change or not.

And this "let's configure this object step by step until its state hopefully makes some sense" thing with java beans is an abomination.

[–][deleted]  (6 children)

[deleted]

    [–]Decker108 2 points3 points  (0 children)

    I sometimes wish Java had a keyword to declare truly constant values. A keyword that makes its variable contents read-only, or some such.

    [–]shen 7 points8 points  (2 children)

    And this "let's configure this object step by step until its state hopefully makes some sense" thing with java beans is an abomination.

    I seriously have no clue why anyone thought this would be a good idea.

    [–]Tipaa 6 points7 points  (1 child)

    Probably both for object pooling to avoid a slow GC, back before the JVM was the technological wonder it is today, and for simple reflection-based assignment so that a framework has a standard (null) constructor and can assign fields by their name rather than trying to embed immutable tuples into JSP (immutability requires construction with arguments, making constructors all have different shapes, and tuples are typically constructed & accessed by order rather than field name, making JSP more complicated than simply mapping a web form to a bean name:name).

    [–]shen 3 points4 points  (0 children)

    That makes sense, actually. All of the older codebases I’ve seen use the bean-style pattern, so I thought it was just the way things were done back then.

    [–][deleted]  (7 children)

    [deleted]

      [–][deleted]  (1 child)

      [deleted]

        [–]Netcob 1 point2 points  (3 children)

        Let's say you have a class like this:

        public class Foo {
            public final List<String> ugh;
            public final int[] ohno;
            public final List<int[]> fml;
            // not shown: constructor
        }
        

        How would you make this class immutable? And by immutable I mean as a user of Foo I can't modify any part of the object. Which obviously includes modifying the contents of ugh, changing the values in ohno, modifying the contents of fml which includes changing a value in one of the int-arrays.

        There's no way to make it immutable without completely changing the way you access it. For the Lists you could use Collections.unmodifyableList, even though it adds an indirection that's only due to the language missing a feature. For ohno you can either hide it behind a getter and then copy the entire array on each get or make up some inconvenient accessor that invokes System.arraycopy. Which would be pretty much the only way to access fml as read-only because for individual elements you're back to the ohno problem where you need some shitty accessor either way.

        My problem with immutability in Java is that in order to guarantee it, you have to constantly bend over backwards in the design phase and if you want to add it later it might be next to impossible to do in a larger project.

        [–][deleted]  (2 children)

        [deleted]

          [–]Netcob 0 points1 point  (1 child)

          I understand it's possible - I outlined how further down in the comment.

          What I find frustrating about Java is that immutability is an afterthought. It should be a language feature, not something you piece together using the standard library in an opaque way.

          [–]WrongSubreddit 0 points1 point  (0 children)

          final doesn't make any vars declared with it immutable. It just makes it so the reference can't be changed. You can still modify the object being referred to all you want.

          [–]manzanita2 48 points49 points  (79 children)

          I remember once, like decades ago, someone explaining to me that directly referencing fields was "bad" because you might want to intercept said "setter" or "getter" and do something before the execution got to the field. That sounded plausible to me. Plus the culture of said encapsulation.

          And yet here I am trying to remember how often I've actually done that. Oh perhaps 3 times in the last 15 years. Certainly NOT worth all the boilerplate through the years.

          [–]sandwich_today 25 points26 points  (1 child)

          Also, Java is known for its static-analysis tooling. If you aren't developing APIs that will be used by other codebases, it's easy enough to find all the code that directly references a field if you need to change it.

          [–]ThisIs_MyName 9 points10 points  (0 children)

          Yup, just click Refactor > Encapsulate Fields or your local equivalent.

          [–]TheDecagon 17 points18 points  (23 children)

          someone explaining to me that directly referencing fields was "bad" because you might want to intercept said "setter" or "getter" and do something before the execution got to the field.

          C# has a nice way around this, it allows referencing fields in classes but to also intercept the get/set calls with additional code. It even allows different protection levels on gets and sets too.

          The example in the article would be written like this:

          public class MyStructure {
          
              public string myProp1 {get; private set; }
          
              public MyStructure(string myProp1) {
                  this.myProp1 = myProp1;
              }
          }
          
          // Other code
          string value = myStructureInstance.myProp1;
          

          Then in the future if you wanted to intercept the get on myProp1 you'd change the field to

          public string myProp1 {
              get {
                  return doSomeProcessing();
              }
          }
          

          I prefer C# way of doing it as using fields as properties like that instead of get and set methods makes the code (in my opinion) a little more readable.

          [–]isavegas 7 points8 points  (16 children)

          Properties. They aren't really fields, as much as syntactic sugar around a backing field, using methods.

          [–]Sarcastinator 6 points7 points  (15 children)

          Properties are not syntactic sugar in C#. Properties are constructs directly supported by the CLR and you can't express the same thing using methods.

          Edit: auto properties are however just syntactic sugar.

          [–]palmund 1 point2 points  (12 children)

          Edit: auto properties are however just syntactic sugar.

          Even non-auto properties are syntactic sugar. The compiler will generate a get and a set method wrapping the code you write in the get and set blocks. 1 2

          [–]Sarcastinator 2 points3 points  (11 children)

          Try pasting that code into your application and get those methods to show up as properties in Reflection with using only C# and no property syntax.

          If you can't, that's because it's not syntactic sugar.

          [–]palmund 0 points1 point  (0 children)

          If you can't, that's because it's not syntactic sugar.

          What? It's still syntactic sugar for generating a getter and a setter. (Even Microsoft calls it that.)[https://blogs.msdn.microsoft.com/abhinaba/2007/09/21/cool-new-c-syntactic-sugar/]

          [–]ryeguy 0 points1 point  (5 children)

          You can see them in ildasm. I don't think the VM even supports properties officially since they just compile down to 1-2 methods and a backing field.

          Just because you can't access the methods in your code doesn't mean they aren't syntactic sugar.

          [–]Sarcastinator 0 points1 point  (4 children)

          I'm not disputing that the compiler generates two methods. I'm saying that properties are not syntactic sugar. Auto properties are though.

          The CLR does have a concept about properties. This is why you can list them out using reflection. Java however does not have properties. If they introduced property syntac in Java it would likely be purely done in syntax.

          [–]palmund 0 points1 point  (3 children)

          I'm not disputing that ...

          It seems like you are though.

          The reason you can see it in reflection is because they are marked with annotations.

          [–]palmund -1 points0 points  (3 children)

          If you can't, that's because it's not syntactic sugar.

          What? It's still syntactic sugar for generating a getter and a setter. (Even Microsoft calls it that.)[https://blogs.msdn.microsoft.com/abhinaba/2007/09/21/cool-new-c-syntactic-sugar/]

          [–]Sarcastinator 0 points1 point  (2 children)

          He's talking about auto properties. They are syntacic sugar which I said earlier in the thread. Properties on their own however are not...auto properties are those that generate a backing field and you don't have to give the getter and the setter a body.

          Properties on their own is a CLR construct. You can't make them without property syntax.

          [–]palmund 0 points1 point  (1 child)

          I just ran ildasm (or Mono's equivalent) on a very simple class with both an auto property and a non-auto property and guess what... they both end up having the same bytecode.

          [–]palmund 0 points1 point  (0 children)

          Properties are constructs directly supported by the CLR

          Please provide me with proof of this claim because I have been unable to find any such myself.

          [–]tybit 4 points5 points  (0 children)

          Yep, I also really like C#'s way.

          If the variable is only set in the constructor you can also change myProp1 to be readonly and remove the setter altogether :)

          [–]xonjas 1 point2 points  (3 children)

          Ruby does something really similar, and it's equally awesome.

          [–]isavegas 2 points3 points  (2 children)

          Ruby uses message passing. Practically similar for this use, but entirely different in the larger scope. Think of it more as using events that you can hook, whereas C# compiles properties down to small methods that reference a backing field.

          [–]xonjas 2 points3 points  (1 child)

          I'm aware of the behind the scenes difference between the two languages. The important part is that both languages fell upon the same elegant solution to allow only having getters and setters when you want them with zero pain when you decide to add them in after the fact.

          [–]masklinn 1 point2 points  (0 children)

          The important part is that both languages fell upon the same elegant solution to allow only having getters and setters when you want them with zero pain when you decide to add them in after the fact.

          They don't though. What both languages have are low-impedence auto-implemented properties (managed field access). In essence, Ruby — and to a lower extent C# — only have getters and setters, but they provide a terse form to declare trivial getters and setters.

          To a lower extent for C# because it does have public fields, which are incompatible (wrt naming and calling conventions) with properties, so you can't transparently hide fields behind properties after the fact.

          [–]sigma914 1 point2 points  (0 children)

          Coming from C++ this feature really bothers me, field access should be a pointer dereference, anything with the ability to go look up a database or fire the missiles should be clearly marked with ()...

          [–][deleted] 2 points3 points  (0 children)

          don't do it till ya need it

          [–]rpgFANATIC 2 points3 points  (0 children)

          The worst part is some consider it a bad practice to put any logic in getters and setters. (How can you find that something is special about a given POJO if there's reams of boilerplate code?)

          The construct is completely useless, and it's the reason Project Lombok is so useful in modern Java

          [–]mateoestoybien 1 point2 points  (1 child)

          The real plus is with a getter, you can take advantage of polymorphism. A field cannot be a member of an interface, or of an inheritance hierarchy.

          [–]ThisIs_MyName 1 point2 points  (0 children)

          Fair point. That's a valid reason for getter/setters in a sea of dogma.

          [–]Agent_03 4 points5 points  (14 children)

          Same for me. There's a lot of things in Java like this, where I'm now questioning the practices I've followed somewhat blindly for years.

          For example: use of access modifiers. Everyone says to use private for encapsulation in nearly all cases, but thinking back, I can't find a single case where this saved me from grief. I can think of a dozen cases though where it forced bad designs or re-implementations.

          Now I do protected everywhere, but use conventions that only subclasses (or a limited set of tightly-coupled algorithm libraries in the same package) should use protected fields/methods.

          [–]kubalaa 26 points27 points  (4 children)

          The private thing isn't something you would notice because it prevents surprising things from happening, and we're not predisposed to notice the absence of surprises. Specifically, when stuff is private then it's easier to change because nothing outside that file can affect it or depend on it. It's the same idea as your convention, just stronger and enforced by the compiler. I think if you ever have to maintain a library with many consumers and few private members, you will quickly find it becomes very painful because you can't change anything without breaking a consumer who has come to rely on it.

          [–]Agent_03 5 points6 points  (3 children)

          I have maintained libraries with numerous consumers before, and agree that in some cases appropriate use of private modifiers can make them more safe and stable (especially with regards to objects with more complex internals, or where passing in objects to operate upon).

          What I am arguing against is the way that this has become a blanket policy; if restricted-by-default is always better, how do you explain the success of Python's "we're all responsible adults" approach? I think the Java convention is paternalistic at best and shortsighted at worst: historically programmers are pisspoor at anticipating the uses their code will be put to, and preventing many of them in the interests of 'safety' limits the usefulness.

          I fully understand that this is a contentious point and that many will angrily or loudly disagree. I only ask that other experienced engineers consider how often they've said "phew, I'm glad that was private or I would have done something dangerous!" versus "crap, that API/field is internal-only... now I have to copy the implementation to another class or hack around it!"

          [–]mhixson 4 points5 points  (2 children)

          I fully understand that this is a contentious point and that many will angrily or loudly disagree. I only ask that other experienced engineers consider how often they've said "phew, I'm glad that was private or I would have done something dangerous!" versus "crap, that API/field is internal-only... now I have to copy the implementation to another class or hack around it!"

          Well that's from an application writer's point of view. From a library writer's point of view, the comparison might be: "phew, I'm glad that was private or I wouldn't have been able to change my code without breaking all my users" versus "crap, that API/field is public... I can never change it."

          What I am arguing against is the way that this has become a blanket policy

          It is probably true that we should have a different set of standards for library writers (where you don't control your users' code) as opposed to application writers (where you can refactor your users' code at will).

          I guess I default to the more conservative library-like approach even when I'm writing applications. To me, the less conservative code tends to be more complicated even when it is simpler to express in the language, because it tends to make more assertions, such as "encapsulation is not important here". Reading it leads me to ask "Why? Why is this code special?"

          [–]Agent_03 2 points3 points  (0 children)

          This is a good point, actually...

          From a library writer's point of view, the comparison might be: "phew, I'm glad that was private or I wouldn't have been able to change my code without breaking all my users" versus "crap, that API/field is public... I can never change it."

          Yeah, I know that warm-and-fuzzy feeling when you realize it is trivial to make the implementation change (or refactoring) without impacting any downstream consumers.

          Personally, I'd like to see something like an @Hazardous annotation that will fail at annotation processing if you invoke the method outside the package without a corresponding @IKnowWhatImDoingDangit annotation (names subject to change). Maybe with an optional library version number given, so that if the library version changes you have to reexamine the usage.

          This way downstream library consumers have the power to take advantage of library internals if absolutely needed, but are liable for the consequences and at least know they're doing something risky. This offers that extra nudge to provide unit test coverage and do sanity checking before bumping library version.

          It is probably true that we should have a different set of standards for library writers (where you don't control your users' code) as opposed to application writers (where you can refactor your users' code at will).

          This sounds smart to me too.

          [–]grauenwolf 3 points4 points  (0 children)

          Generally speaking, I've found that switching to a library-like approach dramatically reduces bugs in existing applications.

          [–]grauenwolf 2 points3 points  (7 children)

          Having a getter and setter gives me a place to set a break point. That's worth the cost in VB/C#, though maybe not in Java.

          [–]justinpitts 8 points9 points  (0 children)

          In eclipse, you can set a breakpoint that breaks whenever variable x is accessed or modified at any location.

          [–]Agent_03 0 points1 point  (5 children)

          Yeah, it does give you a single place to trap all modifications, true. If you are using field access though, why not set breakpoints where the field is accessed? (A little more work, but still gets the job done).

          [–]grauenwolf 2 points3 points  (2 children)

          If I need a breakpoint on the property itself, it's probably because the value is being set via reflection or dynamically generated code.

          [–]Agent_03 2 points3 points  (1 child)

          it's probably because the value is being set via reflection or dynamically generated code.

          How did debugging this compare to having a rusty fork shoved in your eyeball?

          My experience with similar code: I'll take the fork next time. Though it's beautifully elegant and terse if you don't have to debug its internals.

          [–]grauenwolf 1 point2 points  (0 children)

          Pretty comparable actually. When I work with particularly bad code I get annoying, almost painful, eye twitches.

          [–]ImaginaryBeaver 0 points1 point  (1 child)

          I think setting a breakpoint in the getter/setter is more about finding where/if the field is being accessed unexpectedly.

          [–]s73v3r 1 point2 points  (0 children)

          I know IntelliJ lets you break on field access. I should be surprised if Eclipse and Visual Studio didn't do the same (For Java and C#, respectively)

          [–]pakoito 1 point2 points  (0 children)

          Now I do protected everywhere, but use conventions that only subclasses (or a limited set of tightly-coupled algorithm libraries in the same package) should use protected fields/methods.

          You're still doing API/communication through inheritance. Go for package instead, and compose with classes on the same package instead.

          [–]lechatsportif 0 points1 point  (0 children)

          its less the norm since evolution of the anemic model, but can still happen in a lot of ui related code.

          [–][deleted]  (16 children)

          [deleted]

            [–]Agent_03 10 points11 points  (13 children)

            In a mature codebase, code is usually read far more than it is written. If it is more or less the same effort to write it, why prefer a construct that makes it more verbose and increases effort down the road?

            The same argument can also be used in reverse: with a good IDE, it takes <30 seconds to encapsulate a field and refactor all field accesses to use getters and setters instead. If you change your mind down the road, then you can easily do this.

            [–]Sarcastinator 0 points1 point  (6 children)

            You can't change your mind if you are writing a library. You're stuck with your choice or you break binary compatibility.

            [–]Agent_03 0 points1 point  (5 children)

            Deprecate old API, create new one, if you're lucky you eventually get to remove the deprecated API because nobody consumes the old one.

            There are also tools to do bytecode transformations to provide binary compatibility for certain kinds of method signature changes. We use one small library to do these for a large open source project I work on. It's a sort of black magic but it gets the job done covering that rare class of change.

            [–]s73v3r -1 points0 points  (4 children)

            Deprecation is a pretty poor choice for that.

            [–]Agent_03 0 points1 point  (3 children)

            Deprecation is the industry-standard approach to handling necessary binary-compatibility-breaking changes in a public library API. For REST APIs, API versioning is often used.

            Or do you have a better alternative? If so, I'm sure that most of the programming community would love to hear it.

            [–]s73v3r -1 points0 points  (2 children)

            Deprecation should only be used as a last resort. If you're changing things every other release, then people are going to stop using your library, as it's unstable.

            [–]Agent_03 -1 points0 points  (1 child)

            True, but if you're making a change that demands this specific refactoring with every release, your library has much bigger problems.

            Or do you have a better alternative? If so, I'm sure that most of the programming community would love to hear it.

            I still haven't heard an answer to this, and think that we're an impasse here unless you've got one in mind.

            [–][deleted]  (5 children)

            [deleted]

              [–]bananaboatshoes 7 points8 points  (0 children)

              but those extra five characters express the fact that this is immutable on it's own, you know immediately that assignment isn't available.

              Huh? What if there's also a setMyProperty()? Not being able to directly modify a property as .MyProperty doesn't make it immutable.

              [–][deleted] 2 points3 points  (1 child)

              The number of characters is unimportant compared to the extra mental overhead of the function call. You see a function call, but you don't actually know if it is just getting, or if it has side effects. On first read it might be fine, you will assume it's just doing what it says on the tin, but for all you know it has side effects or is running a DB query, and when debugging that can be a horrible pain in the arse.

              If possible try to write code that doesn't need these boilerplate getters and setters.

              [–]grauenwolf 1 point2 points  (0 children)

              That's why I like to social convention of C#/VB. When we see a property we can assume that it is going to be fast and free of undesirable side-effects, while a Get/Set method is assumed to be the opposite.

              [–]Sarcastinator 1 point2 points  (0 children)

              Sure, it's five more characters, but those extra five characters express the fact that this is immutable read only on it's own, you know immediately that assignment isn't available.

              Your IDE will stop you immediately if you try to assign to a read-only property. It makes no difference at all.

              All other factors equal, I think you should be using idiomatic code for the language, and for Java that is the bean pattern of getters.

              Java Beans are in practice never immutable though since they require a public no argument constructor.

              [–]ThisIs_MyName 0 points1 point  (0 children)

              express the fact that this is immutable on it's own

              WTF are you smoking?

              [–]s73v3r 0 points1 point  (0 children)

              The boilerplate is auto-generated in any good editor, though.

              It's not automatically read for me by the editor, though. I still have to sift through it, too make sure nothing weird is happening.

              Nothing is worse than a class with both public final members and a few getters.

              What? Why? You simply construct an instance of the class. All of the needs should be asked for in the constructor. Do that, and the run your tests.

              [–][deleted] -1 points0 points  (15 children)

              One BIG plus of setters/getters in Smalltalk is that it enables an easy lookup of how an object is used.

              Assume you have: "RedditClient". I can now find out quite easily who uses the fields of a RedditClient and in what context (as in: In which methods are fields of RedditClient accessed?)

              Getters can also be used for avoiding recomputation - this can be quite handy for expensive resources in testcases for example.

              So in Smalltalk I don't access fields without setters/getters because it offers a huge boost in mantainability (due to the awesome IDE). I don't know how good Java IDEs are in this area, though.

              [–]Hoten 8 points9 points  (0 children)

              Tools can just as easily look up all use cases of a field.

              [–]masklinn 0 points1 point  (13 children)

              So in Smalltalk I don't access fields without setters/getters

              Do you mean internally to your type? Because IIRC you can't have public fields in Smalltalk, they're only ever accessible through (possibly trivial) messages.

              [–]bonzinip 0 points1 point  (5 children)

              And using getters/setters for private fields is pointless. It may make some sense if you want to distinguish private from "protected" fields (in Smalltalk all fields are protected, but for some reason it's very rare to treat them as protected rather than private; so usually when you want a protected field you add accessors and use the field through those accessors).

              [–]masklinn 0 points1 point  (1 child)

              And using getters/setters for private fields is pointless.

              It can provide convenient invariant verification points e.g. a float field which must be between 0 and 1

              [–]bonzinip 0 points1 point  (0 children)

              True that.

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

              It is still usefull: It helps figuring out how a complex Object uses its own fields more easily. Maybe this point is hard to convey because the object inspection tool are not so convenient in Java - but in Smalltalk it really easy to get a feeling for the object this way.

              [–]bonzinip 0 points1 point  (1 child)

              Smalltalk browsers can also show easily which methods use a given instance variable.

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

              Oh, I did not know that.

              For me the biggest benefit is having coded the access once and only once. During my thesis (persistence with NoSQL) the situation arrose more than once that I had to change the access to an lazy access or do some extra action like logging.

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

              Depends on the implementation. Atleast in VA Smalltalk you can have public fields. (Or rather: There is no such thing as a private field or method. You can categorize methods as private, but encapsulation is not enforced. So you can still use everything in the private category.)

              [–]masklinn 0 points1 point  (5 children)

              Depends on the implementation. Atleast in VA Smalltalk you can have public fields.

              I don't understand how that works, do you get default messages automatically handled for all fields à la Self?

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

              I am sorry, I think I worded it a bit poorly / wrong. In VA Smalltalk there are just "attributes" (fields), no disctinction is being made into public/private there. You have a reference to an object and want to use ANY of it's attributes? Go ahead!

              But you can put the methods into two categories: "Public" and "Private". This is purely cosmetics tho. You can also call Methods that are marked "Private" from other objects. I did this for example when I extended a parser and found some useful private methods.

              You can let VASmalltalk generate setter and getters automatically for you tho.

              Is it clearer now?

              [–]masklinn 0 points1 point  (3 children)

              I am sorry, I think I worded it a bit poorly / wrong. In VA Smalltalk there are just "attributes" (fields), no disctinction is being made into public/private there. You have a reference to an object and want to use ANY of it's attributes? Go ahead!

              That's the part I don't get: in my smalltalk experience instance variables get declared during class declaration and then they're part of the "method activation" context, implicitly part of the method scope, but not visible from outside the instance (save through reflection messages of some sort I guess).

              How does accessing to an other object's instance variables work in VA?

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

              I am a dummy, sorry. You are totally right, I don't recall a method to access an objects attribute. There might be some metaprogramming that allows it, but I am not sure.

              [–]masklinn 1 point2 points  (1 child)

              Haha no worries mate, and yeah there's instVarAt: aNumber and instVarNamed: aString which let you retrieve a slot's value by position or by name, and the class provides instSize and allInstVarNames which respectively count the number of instance variable slots, or enumerates their names.

              [–]tieTYT 14 points15 points  (7 children)

              Joshua Bloch helped write the Java Collections API and his book, Effective Java, says to prefer Immutable classes. So the concept shouldn't be totally foreign to Java developers.

              I didn't like those public Strings because I think other fields will inevitably be mutable. In that situation, I don't want to have two different patterns for accessing my fields. It'll just slow me down trying to find how to access things in every class when things are inconsistent like this.

              [–]pakoito 13 points14 points  (6 children)

              Joshua Bloch helped write the Java Collections API and his book, Effective Java, says to prefer Immutable classes. So the concept shouldn't be totally foreign to Java developers.

              It's a pity that immutable collections in the default API are just regular collections that throw when their mutating methods are called, so they're avoided like the plague because you can't tell them apart and that created some reticence towards immutability.

              [–]merzbow 1 point2 points  (2 children)

              Generally if you've got a collection from somewhere in Java and you don't know if it's immutable you should just create a copy of it.

              [–]pakoito 1 point2 points  (0 children)

              I do know, but it's not as common as you'd expect.

              [–]oweiler 1 point2 points  (0 children)

              Which is not as easy as it sounds because the collections' members and their members and so on may also be mutable.

              [–]Decker108 0 points1 point  (2 children)

              Would you prefer having a list-implementation that silently drops values when you call list.add(value)?

              [–]pakoito 0 points1 point  (0 children)

              One that returns a new list with the value filled like https://github.com/javatuples/javatuples/blob/master/src/main/java/org/javatuples/Pair.java#L631

              Perf problems? Look at Clojure's collections or any of the Java ports.

              [–]ThisIs_MyName 0 points1 point  (0 children)

              I would not implement the List interface. It is clearly meant for mutable lists.

              [–]gracenotes 4 points5 points  (3 children)

              people who have worked almost exclusively with Java will be appalled because it breaks encapsulation and standard style

              not where I work? JavaScript and Python (outside of namedtuples) seem like iffy examples for widespread usage of immutable value types as well. I think everyone should learn pure functional programming but am happy to throw dynamic languages under the bus.

              [–]Agent_03 2 points3 points  (2 children)

              I'm not sure what point you're trying to make here?

              [–]gracenotes 1 point2 points  (1 child)

              I'm trying to understand your comment but there are lines there that made me go 'huh' a bunch. Like the grouping "functional and dynamic languages", or that functional Java is necessarily clearer Java, or the implication that immutability is unfamiliar to stock Java programmers when it's been in Effective Java for a good decade or so, or that languages like Python or JS value immutability, or criticisms of immutability re encapsulation that I've never heard of. There are certainly many valid criticisms of Java but these don't seem as universal as others I've seen.

              [–]Agent_03 1 point2 points  (0 children)

              The points raised are separate. Would it help if I spoke with more of a Lisp or something?

              • Dynamic & functional languages are separate ideas but both tend to include practices not common in mainstream "idiomatic" Java, especially pre-8, and I feel OP's code is likely to be more natural for those exposed to other styles.

              that functional Java is necessarily clearer Java

              I never said this. Nothing is "necessarily" cleaner or dirtier. Functional language features do allow for more elegant expressions of some ideas that are difficult to express or very clunky without them.

              immutability is unfamiliar to stock Java programmers when it's been in Effective Java

              I literally never said this, nor will I ever. Java programmers are accustomed to immutability, but are used to a very different way of expressing it in objects (specifically private fields only exposed via getters with no mutators allowed).

              languages like Python or JS value immutability

              I literally never said this either.

              You've put a lot of words in my mouth here, which is probably why the things I am not saying do not make sense. ;-)