2

I have a class like follows:

 class A{
  // it has some getters and setters
 }

There is another class called builder class which builds class A

class BuilderA{
   // builds A and returns an instance.
}

Now i want to prepare a readOnly class A which make sure that Class newA will have only the getters of ClassA and not the setters.

I am doing this to make sure that if i pass this newA i am safe that nobody can use getters and make any changes to newA which can happen if i use class A directly..

Can anybody tell me how can i achieve this..?

user882196
  • 1,691
  • 9
  • 24
  • 39
  • 1
    Another option would be to use an immutable class (only getters) and create them with a builder. http://en.wikipedia.org/wiki/Builder_pattern – Stefan Dec 16 '11 at 15:02

4 Answers4

1

Here's an example:

public class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class ImmutablePerson extends Person {

    public ImmutablePerson(String name) {
        super(name);
    }

    @Override
    public void setName(String name) {
        throw new UnsupportedOperationException();
    }
}

public class PersonBuilder {
    public static Person createMutablePerson(String name) {
        return new Person(name);
    }

    public static Person createImmutablePerson(String name) {
        return new ImmutablePerson(name);
    }
}

While this works, I don't think it's a great way of designing classes in Java.

Referencing Joshua Bloch's "Effective Java", classes should be immutable unless you have a very good reason why they should be mutable.

SteveD
  • 5,396
  • 24
  • 33
  • Ok, but this is not a type-safe way, you'll only notice at runtime when someone is calling a setter on an `ImmutablePerson`. – Jesper Dec 16 '11 at 15:19
  • Indeed. It's not a good design. That's why I suggest going for an immutable class. – SteveD Dec 16 '11 at 15:44
  • This comment botches use of the extends keyword. This is *wrong* in a lot of ways, as the answerer also felt compelled to say. However the option he provides is also not a solution to your problem. Instead, a solution would be option 3 of https://stackoverflow.com/a/2724848/1502818 – Danny Yaroslavski Jun 08 '17 at 11:33
1

You could easily use a Proxy for this (java.lang.reflect.Proxy), then you just look at the invoked method name (check if it starts with set, roughly). The overhead should be relatively minimal, and it works without needing to code something for each additional class. You could use annotations with further coding for specifying setters which are permitted / denied.

public static boolean isSetter(Method method){
    if(!method.getName().startsWith("set"))    return false;
    if(method.getParameterTypes().length != 1) return false;  
    return true;
}
Chris Dennett
  • 22,412
  • 8
  • 58
  • 84
0

If you want a generic solution to the problem you would have to extract getters and setters into an interface and then use a Proxy to either intercept all methods starting with set or have them annotated(and process annotations in your Handler) and then either do nothing or preferrably throw an UnsupportedOperationException.

This would be overkill if you need it for only 1 or 2 classes tho and comes with a larger overhead in general.

Stefan
  • 838
  • 3
  • 13
  • 28
0

You can extend class A and implements setters that throw an UnsupportedOperationException or just do nothing when called. You can not close access to public setter methods of class A and still be an instanceof class A (via subclassing).

RokL
  • 2,663
  • 3
  • 22
  • 26