ef2011
ef2011

Reputation: 10631

What is the Java equivalent of C++'s const member function?

In C++, I can define an accessor member function that returns the value of (or reference to) a private data member, such that the caller cannot modify that private data member in any way.

Is there a way to do this in Java?

If so, how?

I know about the final keyword but AFAIK, when applied to a method it:

  1. Prevents overriding/polymorphing that method in a subclass.
  2. Makes that method inline-able. (see comment by @Joachim Sauer below)

But it doesn't restrict the method from returning a reference to a data member so that it can't modified by the caller.

Have I overlooked something obvious?

Upvotes: 33

Views: 24674

Answers (9)

John
John

Reputation: 1351

It's up to the returned object to prevent modification. Java doesn't provide declarative/compile-time checking of unmodifiable objects except to the extent that the type lacks mutators.

There is some support in the JDK: methods like Collection.unmodifiableCollection will create an object that will throw runtime exceptions if the client calls collection mutator methods.

If you're truly motivated, you can get compile-time checks by defining read-only interfaces (or classes) that only expose/implement accessor methods on your own. Keep in mind that merely declaring that a method returns a read-only interface will not prevent runtime modification if the client uses introspection and the object provides mutators (that don't throw UnsupportedOperationException).

Upvotes: 0

Lefteris Laskaridis
Lefteris Laskaridis

Reputation: 2322

You either return an immutable object, or return a copy of the private instance variable. This way, the object's internal state is "protected" from modification, i.e.:

private MyMutableObject mutable = ...

public MyMutableObject getMutableObject() {
   return new MyMutableObject(this.mutable);
}
`

Upvotes: 5

Anthony Accioly
Anthony Accioly

Reputation: 22461

When you do something like this:

Object2 obj2 = obj1.getObj2();
obj2 = new Object2();

The original private member (obj1.obj2) remains as it were before (just to be sure that you grasped that concept). You can just omit the setter to obj2 so that the inner field cannot de changed.

If you want Object2 fields to be immutable you will need to apply the same pattern (private fields, no setters).

This answer your question?

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533500

One way to avoid this issue is to no expose the data structure (another is returning a copy, or an immutable wrapper)

e.g. instead of

public List<String> getSomeList();

have

public String getSomeElement(int index);

Upvotes: 0

Joachim Sauer
Joachim Sauer

Reputation: 308031

There's no equivalent to the C const "type modifier" in Java (sadly).

The closest you can get is to return an immutable object or an immutable wrapper around a mutable object.

Immutability is not a language feature of Java, however, so you'll have to rely on Libraries.

Examples of immutable objects are:

  • the primitive wrappers Integer, Character, ..
  • String
  • File
  • URL

Commonly used immutable wrapper (i.e. wrappers around mutable types that prevent mutation) are those returned by the Collecton.unmodifiable*() methods.

Upvotes: 24

phtrivier
phtrivier

Reputation: 13361

I don't think there is a way to that in Java for non primitive objects (you're always passing around references to such objects). The closest you could do would be to return a copy of the object (using clone or something like that) ; but that would not be very idiomatic Java.

I you want to give access only to the 'visible' part of a member object, what you could do is create an interface with the visible part, and return this interface. For example :

public interface Bar {
     public int getBing();
}

public class BarImpl implements Bar {
     private int bing;
     public int getBing() {
        return bing;
     }
     public void setBing(int bing) {
        this.bing = bing;
     }
}

public class Foo {
     private BarImpl bar;

     public Bar getNonModifiableBar() {
         return bar; // Caller won't be able to change the bing value, only read it.
     }
}

Upvotes: 1

no.good.at.coding
no.good.at.coding

Reputation: 20371

You could return a copy of the member, thus changes will not be reflected in the object the private reference points to. With primitives, of course, this problem doesn't exist.

Be mindful of memory usage, however! This might not be the right solution for all situations. In that case, an immutable object as suggested in another answer might be the way to go.

Upvotes: 2

Erik
Erik

Reputation: 91270

This does not exist in java. final and const have different semantics, except when applied to a variable of a primitive type. The java solution typically involves creating immutable classes - where objects are initialized in construction and provide no accessors allowing change. Example of such classes would be e.g. String or Integer.

Upvotes: 8

Mark Peters
Mark Peters

Reputation: 81074

You haven't overlooked anything. There is no way in pure Java to do so. There might be libraries which provide some subset of this using annotations, but I don't know any offhand.

The way you pass back a reference to immutable data is to make the class you pass back immutable, plain and simple. There are a couple of library functions to help you produce an immutable view of some data in some very limited but common cases. Here's one example:

private List<String> internalData;

public List<String> getSomeList() {
    return Collections.unmodifiableList(internalData);
}

Upvotes: 4

Related Questions