A question about Java

Started by
6 comments, last by elFarto 14 years, 1 month ago
In C++ I always try to const-correct anything I write. But in java, it seems to me that const-correctness is not very important. Maybe I am saying that because right now in my school they do not talk any about const-correctness in java. Is it just me or is java not very serious about const correctness, or is my school teaching badly practice( or should I say teaching even more bad practice) ?
Edge cases will show your design flaws in your code!
Visit my site
Visit my FaceBook
Visit my github
Advertisement
Java doesn't have language concept of const-correctness in same way as C++.

Personally, I prefer single-assignment where viable.
  final Map<Integer, String> urls = new HashMap<Integer, String>();...  public void build(Connection conn, UrlTransformer transformer) throws SQLException     {        urls.put(0, "-");        final Statement stat = conn.createStatement();        try {            final ResultSet rs = stat.executeQuery("...");                        try {                while (rs.next())                 {                    final int id = rs.getInt(1);                     final String url = transformer.get(rs.getString(2));                                        urls.put(id, url);                }            } finally {                rs.close();            }        } finally {            stat.close();        }    }

The rule is quite simple. Put final in front of all variables. Remove it front those that really cannot be final, such as those that will change during life-time of the object. Prefer to have all members final.

final doesn't do anything. It doesn't result in faster code, less memory, or similar, it is universally ignored by VM and compiler.

But it does give a sanity check - final fields that have not been initialize will raise compile-time warning, and local variables will result in single-assignment - there is no real reason why variables should be reassigned.

And variable or field that is not final is assumed to be mutable. Prefer to avoid those, since changing values lead to considerably more complex code with regards to error handling and invariant checking. Sadly, mutable state is preferred by most of Java coders.

Quote:is my school teaching badly practice

This will be the last of your worries when dealing with real world Java.

There have been proposals that all variables and fields in Java should default to final, and only special cases should declared as mutable. While I personally agree, it isn't going to happen.
If I recall correctly, Java doesn't actually have const-correctness to the same degree that C++ has. One can declare compile-time constants the way one might in C++ using the final keyword, but despite const apparently being a reserved word Java does not have const methods or const method parameters. Declaring a method as "final" only prevents it from being overridden.

edit: ninja'd
edit2: fix'd, thanks DevFred

[Edited by - Oberon_Command on February 26, 2010 11:42:48 AM]
It's just not supported, the Java designers decided to leave that stuff out.

I think it makes sense to leave it out of the Java world. You can't have const member functions unless you have a concept of data ownership. C++ has a concept of data ownership:

class MyClass{    Object ownedObject;    Object* someoneElsesObject;    void modifyOwned() const    {        ownedObject.modify(); // <-- this is a compile error    }    void modifySomeoneElses() const    {        someoneElsesObject->modify(); // not an error    }};


In Java, all non-primitive fields are secretly pointers, the compiler doesn't know whether a field is "owned" or not. So you can't have const member functions.

Then if you don't have those, you can't pass around const pointers to objects, because the compiler doesn't know which methods are safe to call.

Anyway, that's the long answer. The short answer is that they probably left it out because const-correctness introduces so much damn complexity (such as needing to have const and non-const versions of functions, const and non-const iterators, and the occasional const_cast).
Quote:Original post by Oberon_Command
If I recall correctly, Java doesn't actually have const-correctness to the same degree that C++ has. One can declare compile-time constants the way one might in C++ using the final keyword

final means one and exactly one assignment. While useful, it doesn't affect the actual instance (for non-primitive types). So final instance can be modified.

final can be applied to parameters as well, but I've found it adds too much clutter.

It also plays well with IoC/DI:
class Foo {  final IBarSystem bs;  Foo(IBarSystem bs) { this.bs = bs; }  void foo(...) {};}

Fields should be initialized once, provided by factory, and the member methods should modify their local state only. But this is not a hard rule, it's frequently needed, so final gives a hint at which systems are provided externally, and which are managed locally by instance.

final also eliminates the need for getters/setters, since they can only be assigned once.

Quote:Declaring a method as "final" only prevents it from being overloaded.

This one is of questionable use in practice due to use of interfaces and private functions. General consensus seems to be that public members should be extensible, the rest should be private. final just complicates things.


As said, it's mostly a design and sanity check tool, but one can go either way.

Quote:The short answer is that they probably left it out because const-correctness introduces so much damn complexity (such as needing to have const and non-const versions of functions, const and non-const iterators, and the occasional const_cast).


IMHO, it eliminates complexity. Immutability and single assignment results in considerably simpler code for same reasons RAII does (RAII instance cannot exist unless it is fully initialized, which simplifies many code paths).

C++ const-correctness however is verbose and full of issues. But that is not same as immutability itself, especially due to historical and practical issues with exceptions and general complications related to resource management inherent in language.

C# is somewhat better in this regard (readonly, const, sealed, struct vs. class).
Quote:C# is somewhat better in this regard (readonly, const, sealed, struct vs. class).

How is it better? I thought the general consensus was that more keywords->complexity meant more trouble?
Quote:Original post by Oberon_Command
Declaring a method as "final" only prevents it from being overloaded.

You can overload final methods just fine. What you cannot do is override them.
Quote:Original post by Antheus
final doesn't do anything. It doesn't result in faster code, less memory, or similar, it is universally ignored by VM and compiler.

That's not entirely true, the VM loves static final fields, and will inline them where possible.

I had some code that calculated an offset based on the x,y,z co-ordinates of a block. I had all the parameters (width, height, depth, and lots of derived ones such as bitmasks) as static final. Just for kicks I timed the static and static final versions of this class, and the static final one was clearly faster.

Regards
elFarto

This topic is closed to new replies.

Advertisement