24

I was wondering if there was an equivalent to c++'s const in Java. I understand the final keyword, but unfortunately I cannot use that to declare a functions return value final. Instead, it always ensures the function cannot be overridden, correct?

Basically, I want to make sure a given returned class cannot be modified and is read only. Is that possible in Java?

lowq
  • 628
  • 6
  • 18
  • 1
    Out of curiosity... why do you want to impose such a limitation on the returned value? – 6502 Oct 25 '11 at 19:46
  • 16
    @6502 immutability helps to avoid many bugs. – Tamás Szelei Oct 25 '11 at 19:48
  • Say class A has a field of class B, which has a field of class C. If class A calls a getC() method on class B, class A can now freely modify and possibly disrupt class C. C++'s const regulates this. I'm really just curious as to if this is standard in Java like it is in c++. – lowq Oct 25 '11 at 19:55
  • @user984799: The final answer is no. You can make a member be `const` via `static final`, but Java will decide at compile time if it will be an actual constant. Thus, `static final iFoo = 3` will be a compile-time constant (and thus its value will be baked into the compiled code directly), but `static final int iRand = (int)(Math.random()*20);` will, though legal, not be a constant. – Brian Oct 25 '11 at 20:03
  • 2
    @Brian `static final` (no idea what the static has to do here though) is a rather different concept than `const` in c++ for objects and sadly much weaker. – Voo Oct 25 '11 at 20:09
  • 1
    See also http://stackoverflow.com/questions/4971286/javas-final-vs-cs-const/4971330#4971330 – BlueRaja - Danny Pflughoeft Oct 25 '11 at 20:21
  • @Voo: `static final` is different from `final` in that, if the field is a string or a primitive and can be determined at compile time, the Java compiler will inline it. Yes, this does mean that if you recompile a class, things which depend on that class may behave unexpectedly if you don't recompile them. **That** special case is similar to a C++ `const`, particularly if you are concerned with efficiency. If you're concerned with using `const` to protect yourself from bad code, that information is not especially helpful. – Brian Oct 25 '11 at 22:05
  • @Brian Java does the same thing (ie inlining) with final variables, so the only difference is that we don't have to set the field in the constructor for the static variable (which really is true for any static variable, final or not). – Voo Oct 25 '11 at 23:12

6 Answers6

21

Basically, I want to make sure a given returned class cannot be modified and is read only. Is that possible in Java?

Not directly, but one workaround is an immutable object.

Example -

public final Foo {
    
    private final String s;
    
    public Foo(String s){
        this.s = s;
    }
    
    // Only provide an accessor!
    public String getString(){
        return s;
    }
}
MC Emperor
  • 22,334
  • 15
  • 80
  • 130
mre
  • 43,520
  • 33
  • 120
  • 170
  • 3
    You should also add the final modifier to the declaration of `s` to disallow modifications by other methods.(+1) – stacker Oct 25 '11 at 19:48
  • Does that mean I have to declare an Immutable object counterpart for each class I want to be read only at some point? – lowq Oct 25 '11 at 19:50
  • 13
    IMHO, this is a workaround, **NOT** an equivalence! There is no other way around this issue than this extremely verbose and error prone way though. – Shautieh Oct 25 '11 at 20:03
  • @user984799 if you declare a field as final it can only once assigned by static initaization or constructor. See also chapter 4.12.4 final Variables at http://java.sun.com/docs/books/jls/download/langspec-3.0.pdf – stacker Oct 25 '11 at 20:06
  • @user984799 - No, it doesn't. An immutable object is not equivalent to a const-qualified return value in C++. It is one of several workarounds. See my answer below for more. – Andy Thomas Oct 25 '11 at 20:15
15

Java does not support const-qualification of references to objects.

Workarounds include the following:

  • Immutable objects.
  • Unmodifiable views of modifiable objects (for example, those returned by Collections.unmodifiable*()).
  • Read-only interface types
  • Defensive copies.

Immutable objects prevent modification by the recipient, but they also prevent modification through any reference. They are not equivalent to C++ const pointers/references.

Closest are read-only interface types. You could map a const-correct C++ class to two Java units, one an interface with only the const-qualified methods.

This is sometimes useful, to control what can modify an instance of the class. However, it's not done as frequently as in C++.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
4

The "final" keyword means const. But the use of final in java is much different than C++ Only fields or local variables can be final. A final class is not a const class but a sealed class that cannot be inherited. A final method is a sealed method, a method that cannot be overridden.

In C++ there is the concept of "const type" but in java you have only the concept of const field, const method (not-overridable) and const class (not-inheritable).

Salvatore Previti
  • 8,956
  • 31
  • 37
1

No

Java does not support the concept of constness as C/C++ use it.

The Java equivalent to this Foo class cannot be written.

class Foo
{
public:
   std::vector<Bar>& bars( void ) const
   { return m_bars; }
private:
   std::vector<Bar> m_bars;
};

However, Java has another approach, using interfaces.

class Foo
{
public:
   ReadonlyList<Bar> bars( )
   { return m_bars; }
private:
   ArrayList<Bar> m_bars;
};

Java's final keyword is more similar to Foo * const than any other c++ concept. Note that Foo const* is very common and useful, while Foo * const is less so.

Community
  • 1
  • 1
deft_code
  • 57,255
  • 29
  • 141
  • 224
  • Your code should say: **const** std::vector& bars( void ) const, otherwise it will not compile. And in C++ you **won't** be able to call any of the mutating (non-const) operations on the Bar's from the returned vector reference . As I understand Java, with ReadonlyList you can't modify ReadOnlyList but you can still modify the Bar's it contains. – kyku May 12 '19 at 18:59
0

I think you want a immutable object. An object is considered immutable if its state cannot change after it is constructed.

To do that you need

  • ensure the class cannot be overridden - make the class final, or use static factories and keep constructors private
  • make fields private and final force callers to construct an object completely in a single step, instead of using a no-argument constructor combined with subsequent calls to setXXX methods
  • do not provide any methods which can change the state of the object in any way - not just setXXX methods, but any method which can change state.

    public final class SomeThing{

    public Something(String name) {
        fname=name
    }
    
    private final String fName;
    
    public String getName() {
          return fName;
    }
    

    }

Ehab Al-Hakawati
  • 982
  • 4
  • 11
  • 32
0

Java specifically discarded some features of C++, const is one of it. This conscious decision can be reflected by the fact that const is a reserved word in Java (but not used)

The designers probably thought that the feature is really annoying and not really useful. I had that feeling when I was a C++ coder. Certain kind of static checking is just way too much.

irreputable
  • 44,725
  • 9
  • 65
  • 93