How can we get immutable object if class did not implement cloneable - java

I have few issues/doubts to fill values in a HashMap
I want a HashMap to accept "Student" as key and "Details" as value.
Since key to a hashMap should be immutable I have some doubts how can this be dealt if
Student class did not cloneable
Student class has reference to which in turn have reference to "Lab"
public class Student {
private String id;
private String name;
private Department dept;
public Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
public Department getDepartment()
{
return this.dept;
}
}
public class Department {
private String deptId;
private Lab lab;
public Department(String deptId, Lab lab)
{
this.deptId=deptId;
this.lab=lab;
}
public void setLab(Lab lab)
{
this.lab=lab;
}
}
public class Lab {
private String labId;
private String labName;
public Lab(String labId, String labName)
{
this.labId=labId;
this.labName=labName;
}
}
public class StudentDetails
{
private String fatherName;
private String address
public StudentDetails(String fatherName, String address)
{
this.fatherName=fatherName;
this.address=address;
}
}
public class StudentMaintainer {
public static void main(String[] args)
{
StudentDetails stDetails= new StudentDetails("John","Mumbai");
Lab lab= new Lab("100","CS");
Department dept= new Department("900", lab);
Student st = new Student("3000",dept);
Map<Student,StudentDetails> studentMaintainer= new ArrayList<>();
studentMaintainer.put(st,stDetails);
}
}
Now Even if Student is cloneable, I can get reference of Department and call setLab() which changes the StudentObject. (Am I wrong?)
Now if Department and Lab are from 3rd party jars, how can I use Student Object in my Map if Student hashCode is (primeNumber+Student.id+Department.id+Lab.id).hashcode() [just some weird case];

Immutability has nothing to do with Cloneable as far as I understand it, and in fact just the opposite. Immutability has more to do with declaring the class final and using immutable fields, non-overridable methods, no setter methods, getter methods that return deep copies of fields or immutable fields, etc... Please read A Strategy for Defining Immutable Objects for more on this.
Also your code has a pseudo-constructor:
public void Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
A true constructor should not be declared to return anything, not even void. Better would be:
// note the difference?
public Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
Also, your Student class should properly override equals and hashCode if it is to work well as a key for a HashMap.

Now Even if Student is cloneable, I can get reference of Department
and call setLab() which changes the StudentObject. (Am I wrong?)
You are correct. This can happen, and can cause your Student class to appear to be mutated. For an instance of Student to be immutable, you must not be able to modify any of its fields[0]. That includes calling something like a setter method on one of its fields.
Now if Department and Lab are from 3rd party jars, how can I use
Student Object in my Map if Student hashCode is
(primeNumber+Student.id+Department.id+Lab.id).hashcode() [just some
weird case];
That is a very good question. You obviously can't just change the classes to be immutable, since you don't have control over them, so you may have to get a bit creative. Possible solutions:
if the third party objects you want to use are interfaces, you could implement the interface with your own type, where the body of every mutator method throws an exception (think e.g. java.util.Collections.unmodfiableList). This has the benefits that you can still refer to the third party class in your codebase, but the drawback that calling mutator methods will fail at runtime, rather than at compile time.
write adapters in your own codebase, like this:
public final class MyImmutableDepartment {
private final MyImmutableLab lab;
private final String departmentId;
public MyImmutableDepartment(Department thirdPartyMutableDepartment) {
this.departmentId = thirdPartyMutableDepartment.getId();
this.lab = new MyImmutableLab(thirdPartyMutableDepartment.getLab());
}
// getters and the MyImmutableLab class left as an exercise
}
This has the advantage that you know at compile time, the classes cannot be mutated.
The downside in both approaches is that you basically have to mirror every class from the third party library, to ensure they're immutable.
I don't think there's any other alternatives.
[0] there are some cases where this is possible, and can be used for internal caching, but it's a decent guideline to stick to when learning.

Student does not need to be immutable! Specifically, the requirement is that the behavior of equals/hashCode doesn't change when the key is in the HashMap.
This can be accomplished in three ways:
Don't implement equals/hashCode. If you use the default reference equality, it doesn't matter how you mutate the key. To clarify intent, override those methods, explicitly call super.equals, and make them final.
Don't include any fields that will mutate in your calculation of equals/hashCode. Or, if the properties of a field may change but not the reference, use reference equality (==) instead of field.equals() and call System.identityHashCode(field) instead of field.hashCode()
Don't mutate the object while it is used as a key in the HashMap. A bit dangerous, but works fine if references aren't held by code beyond your control. Document the requirement.
But, in your concrete example, each student has an id. Why would you use any other properties when implementing equals/hashCode.?

Related

Is this class immutable or not?

The below class doesn't have final keyword but its member variables are private and final and the class exposes no mutate/set methods. Is this class immutable or not?
public class Abc {
private final int id;
private final String name;
public Abc(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
The class itself is immutable, yes - if you create an instance of just Abc, no aspect of that can be changed after the instance has been created.
However, that doesn't mean that any code receiving a parameter of type Abc can assume it's immutable with all the benefits that carries... because the class isn't final. It's entirely possible for an object of a type compatible with Abc to be mutable:
public class Mutable extends Abc {
private String value;
public Mutable(int id, String name) {
super(id, name);
}
public void setValue(String value) {
this.value = value;
}
#Override public String toString() {
return value;
}
}
Now imagine you've got code which deals with an Abc:
public class AbcConsumer {
private final Abc abc;
public AbcConsumer(Abc abc) {
this.abc = abc;
}
// No need to create a defensive copy or anything like that...
// abc is immutable, right?
public Abc getAbc() {
return abc;
}
}
Here the consumer assumes it's fine to treat Abc as if it's an immutable class - but if someone creates an AbcConsumer by passing in a Mutable instance instead of "vanilla" Abc instance, it could cause problems.
That's why it's generally a good idea when you're creating an immutable type to make it final as well - that way any consumers know that if they receive a reference with that type, it's definitely immutable.
To put it another way: yes, the Abc class is immutable... but you can't assume that a reference with a compile-time type of Abc refers to an immutable object.
As presented, yes, the class is immutable.
The "final" keyword on a class declaration prevents it from being extended - it's not related to immutability (unless your variables are declared public or protected).
Edit; "not related" is a poor choice of words, please see Jon Skeet's answer below
No, it is most likely not.
A problem is terminology. What do you mean by class? If you mean this code, sure, it's immutable. But 'this code' is not something that is particularly relevant to the concept of immutability. That usually makes a lot more sense if we consider it: this type.
As in, is the type Abc immutable?
As in, given:
public void foo(Abc abc) { ... }
is it safe to assume that the received abc couldn't possibly change?
And then the answer is no. That is not safe to assume: The type Abc is mutable.
The reason is that someone could make this:
class SneakyAbc extends Abc {
private int id;
public void setId(int id) {
this.id = id;
}
public String getId() {
return id;
}
}
This is why immutable classes are virtually always made final, to fully guarantee it.
Depending on how fancy you want to paint with the brush of 'what does this term mean', if all methods of Abc are final, you can consider it immutable as well if you really want to: Whilst the class does not need to be immutable (a subclass can add a new non-final field and create getters and setters for this), all the stuff you can 'witness' from the Abc type, assuming you don't use reflection, do appear immutable.
Exactly what definition of immutable you go with would be required knowledge to delve any further.
Note that something like java.io.File has only final fields and is final, and yet, it has easily observable state that can be modified: just.. delete the file, and voila you can see it. You can pull similar stunts with an IdentityHashMap to create a faux but nevertheless very observable 'field'.
Thus, 'immutable' as a concept: Useful. As a boolean flag to bestow upon a certain type or some java source file: Not useful.
Records
Other Answers directly addressed your questions about immutability, class being marked final, and subclasses being mutable. I’ll add an alternative option to more briefly accomplish your goal of immutability: Records.
Java 16 brings the new records feature. If the main purpose of your class is to immutably and transparently carry data, define your class as a record. The compiler implicitly creates default constructor, getters, equals & hashCode, and toString.
A record is implicitly final, so no risk of a subclass becoming mutable.
Declare the properties in parentheses. By default, you need not put anything in the curly braces body of a record.
record Abc ( int id , String name ) {}
Instantiate like any other class.
Abc x = new Abc ( 42 , "Snuffleupagus" ) ;
The implicit getter methods are simply the property names. The JavaBeans-style get…/is… method naming is not used. (You could add such methods if required.)
System.out.println( x.name() ) ;
Snuffleupagus
It is mutable if its internal states can be changed after the class is created.
In your example, although there is no class final, the inside situations cannot be changed again because of final keyword. In this way, the class becomes immutable again

Is My java class Immutable

Please see i am not asking what is immutability, i understand immutability but question is more how to make an immutable class when you are giving reference to a mutable object. Moreover my class failed the check with mutability detector project, hence requesting your view.
I have created a Immutable class EmpAndAddress.java and it has reference to a mutable class EmpAddress.java which is cloneable.
I have followed the java rules and tried to test my class using mutability detector but my class is failing the immutable test. Just want to check if I am missing something. In my Immutable i am always creating new Object of type EmpAddress mutable to follow the rules.
http://mutabilitydetector.github.io/MutabilityDetector/
1. Mutable EmpAddress.java
public class EmpAddress implements Cloneable{
public String empCity;
public int zipCode;
public EmpAddress(String empCity, int zipCode) {
super();
this.empCity = empCity;
this.zipCode = zipCode;
}
public String getEmpCity() {
return empCity;
}
public void setEmpCity(String empCity) {
this.empCity = empCity;
}
public int getZipCode() {
return zipCode;
}
public void setZipCode(int zipCode) {
this.zipCode = zipCode;
}
protected Object clone() throws CloneNotSupportedException {
EmpAddress clone=(EmpAddress)super.clone();
return clone;
}
}
public final class EmpAndAddress implements Cloneable {
private final int empId;
private final String empName;
private final EmpAddress eAddr;
public EmpAndAddress(int empId,String empName,EmpAddress eAddr){
super();
this.empId = empId;
this.empName = empName;
this.eAddr = new EmpAddress(" ", -1);
}
public int getEmpId() {
return empId;
}
public String getEmpName() {
return empName;
}
public EmpAddress geteAddr() throws CloneNotSupportedException {
return (EmpAddress) eAddr.clone();
}
}
The only problem I see is that you are actually not using the EmpAddress instance being passed to the EmpAndAddress constructor. I doubt that was intentional on your part.
In any case, to ensure that your class is immutable despite a reference to a mutable object is by performing clones both when receiving the EmpAddress instance in the constructor, and when returning an instance from the geteAddr() method.
You are already doing that inside the geteAddr() method, so you're ok on that front.
All that you are missing is fixing your constructor, like this:
public EmpAndAddress(int empId,String empName,EmpAddress eAddr){
this.empId = empId;
this.empName = empName;
this.eAddr = (EmpAddress) eAddr.clone();
}
The MutabilityDetector code is checking that the class is transitively immutable. It is not sufficient for the class itself to be immutable. The types of all of the classes fields must also be immutable. The child objects referenced by the fields are assumed to be part of the state of the parent object, so changing a child object changes the parent.
In your case, the (supposedly) immutable class EmpAndAddress has a field whose type is mutable. Furthermore, the field in an EmpAndAddress object is initialized with a value that is passed as a constructor argument. If the caller of the constructor keeps the EmpAddress reference, it can change the state of the EmpAndAddress object.
Full disclosure: author of Mutability Detector here... with a loooong answer.
If we start out with the class you defined in your question, and assert on it being immutable, like so;
#Test
public void isImmutable() {
assertImmutable(EmpAndAddress.class);
}
You get a test failure with the following message:
org.mutabilitydetector.unittesting.MutabilityAssertionError:
Expected: org.mutabilitydetector.stackoverflow.Question_32020847$EmpAndAddress to be IMMUTABLE
but: org.mutabilitydetector.stackoverflow.Question_32020847$EmpAndAddress is actually NOT_IMMUTABLE
Reasons:
Field can have a mutable type (org.mutabilitydetector.stackoverflow.Question_32020847$EmpAddress) assigned to it. [Field: eAddr, Class: org.mutabilitydetector.stackoverflow.Question_32020847$EmpAndAddress]
Allowed reasons:
None.
(I've defined both classes as a static inner class, hence showing up as $EmpAndAddress in the message, but ignore that for now.)
Another answer to this question is totally correct. EmpAndAddress is considered mutable because EmpAddress is considered mutable, and every field of an immutable object should also be immutable. EmpAddress is mutable for several reasons: can be subclassed; has public non-final fields; setter methods. The first question is, why does cloning the EmpAddress field in the getter not help make it immutable? Well, in this case it does happen to make it immutable, but Mutability Detector doesn't perform the kind of analysis required to be confident of it. Mutability Detector doesn't have any special analysis for safely cloning mutable objects when letting them "escape" to callers. This is because it's very easy to misuse .clone and introduce mutability. Imagine if EmpAddress had a mutable field, like List, you can observe mutation like so:
#Test
public void go_on_try_to_mutate_me_now_i_have_a_list_field() throws Exception {
EmpAndAddress e = new EmpAndAddress(1234, "John Doe");
assertThat(e.geteAddr().getMyList(), is(Collections.<String>emptyList()));
e.geteAddr().getMyList().add("Haha, I'm mutating you");
assertThat(e.geteAddr().getMyList(), is(Collections.<String>emptyList())); // Fails because list now has one element in it
}
This is because Object.clone does not perform deep copies. It's only safe in this case because the fields cloned in EmpAddress are immutable (String and primitive int). Mutability Detector could try to recognise safe usages of .clone, but it would probably be very fragile. Because it can't be confident that your class is immutable, Mutability Detector decides it is mutable.
You are correct that creating a new Object of type EmpAddress is helping to make the class immutable, that's because it is "protecting" the instance, keeping it private, where no other code can access it. If the constructor took an instance and assigned it to a field, whoever passed the parameter to the constructor could modify it, thus mutating any instance that used it for a field. Like in this example:
#Test
public void mutate_object_by_giving_it_a_parameter_then_modifying_it() throws Exception {
EmpAddress empAddress = new EmpAddress("New York", 1234);
EmpAndAddress e = new EmpAndAddress(1234, "John Doe", empAddress);
assertThat(e.geteAddr().getCity, is("New York"));
empAddress.setCity("Haha, I'm mutating you");
assertThat(e.geteAddr().getCity(), is("New York")); // fails because city has been changed
}
So, what to do about it? There are a couple of options.
Method 1: Override Mutability Detector because you know better
Change your test to add an "allowed reason" to be mutable. That is, you are satisfied the failure is a false positive, you want to catch other potential errors which introduce mutability, but ignore this case. To do this, add code like the following:
#Test
public void isImmutable_withAllowedReason() {
assertInstancesOf(EmpAndAddress.class, areImmutable(),
AllowedReason.assumingFields("eAddr").areNotModifiedAndDoNotEscape());
}
You should be very sure about this before you take this option, and if you are new to immutable objects, I would recommend not doing this, so that you can learn to create immutable objects more safely.
Method 2: Make EmpAddress immutable as well, like so:
#Immutable
public static final class ImmutableEmpAddress {
private final String empCity;
private final int zipCode;
public ImmutableEmpAddress(String empCity, int zipCode) {
this.empCity = empCity;
this.zipCode = zipCode;
}
public String getEmpCity() { return empCity; }
public int getZipCode() { return zipCode; }
}
Then when you return it as a field from EmpAndAddress you don't need to clone it. This would be an ideal solution.
Method 3: Create an immutable adapter
However, in some cases you can't make EmpAddress immutable. Maybe the code is in a different library, or it's used by a framework that needs to set fields on it with reflection (such as Hibernate, or other JavaBean libraries). In this case you could create an immutable adapter like so:
#Immutable
public static final class ImmutableEmpAddressAdapter {
public final String empCity;
public final int zipCode;
public ImmutableEmpAddressAdapter(EmpAddress mutableAddress) {
// perform a deep copy of every field on EmpAddress that's required to re-construct another instance
this.empCity = mutableAddress.getEmpCity();
this.zipCode = mutableAddress.getZipCode();
}
public EmpAddress getEmpAddress() {
return new EmpAddress(this.empCity, this.zipCode);
}
}
Then in EmpAndAddress could look like this:
public static final class EmpAndAddress {
// some code ommitted for brevity
private final ImmutableEmpAddressAdapter immutableEmpAddressAdapter;
public EmpAndAddress(int empId, String empName){
this.immutableEmpAddressAdapter = new ImmutableEmpAddressAdapter(new EmpAddress(" ", -1));
}
public EmpAddress geteAddr() {
return immutableEmpAddressAdapter.getEmpAddress();
}
}
Although this technique would require more code, it makes it very explicit to other readers of this class that EmpAddress has an immutable field, and doesn't rely on fragile behaviour of Object.clone
This is also a good technique if you want to make a class immutable, but you have to make many code changes to do it. This allows you to gradually introduce an immutable version in more and more places in a codebase until eventually the original mutable class is only used at the margins of your system, or even disappears entirely.
I hope this anwser, and Mutability Detector have been useful in learning how to create immutable objects.

Java arraylist indexof

Here is my class animals.java:
public class animals {
String Name, ID;
static ArrayList<animals> animalData = new ArrayList<animals>();
public animals(){}
public animals(String name, String id){
super();
this.Name = name;
this.ID = id;
}
public void addAnimal(String name, String id){
animalData.add(new animals(name, id));
}
public int search(String name){
return this.animalData.indexOf(name);
}
}
When I add an animal name with an id it works normally, but when I use search method I saw only -1. Maybe I try override method equals or indexof in this class? help me for this
Thank you and sorry for my bad english..
You are adding instances of animals to the list. You are searching for the instance by name. Since animalData does not contain any instances of String, indexOf() will never return an index.
If you want to access an instance of animals by the name, you should use a Map<String,animals>.
Map<String,animals> animalMap = new HashMap<String,animals>();
animalMap.put("Mat", new animals("Mat", "id");
animals animal = animalMap.get("Mat");
The proper use of indexOf() is to pass in an instance that is equal to an instance already in the collection. As others have pointed out, this will require you to define equals() to define what makes two instances equal. You should also override hashcode() when you override equals() because there is an assumed correlation.
Note: The convention is to use CapitalCase for class names. Also, the class name should not be plural. You will have many instances of Animal, you may later make a class that is a collection of Aniamals, but that should not be the name of the main class.
Yes, you need to override equals() and hashcode() methods when you use objects in collections and perform lookup based on object.
indexOf() returns object because it just returns object at that perticular index. But, when you do object based lookup, if equals() and hashCode() are not overridden, equals() may fail and you get unpredictable results.
You need to define an "equals" method
You're looking for a String...
You'd better use a HashMap I think...
But yeah you have to change your structure(which isn't very efficient)
Here is the code I would use:
public class animals {
String Name, ID;
static Map<String, animals> animalData = new HashMap<String, animals>();
public animals(){}
public animals(String name, String id){
super();
this.Name = name;
this.ID = id;
}
public static void addAnimal(String name, String id){
animalData.add(new animals(name, id));
}
// Returns null if no registered animal has this name.
public animals search(String name){
return this.animalData.get(name);
}
}
This way, you make the search method much faster (O(1)), you don't need to override the equals method anymore.
Note that if animalData is static, you should consider to make addAnimal() static as well since it's sort of a 'setter' for aniamalData.

Immutability property in java

I know that when it comes to passing objects in java, the reference of object is passed as value. So what ever changes you make to that object is reflected in the original object as well. To avoid this we make use of immutability property in java.
So my question is, I have created an immutable class Employee, When I pass an object of this Employee class to some method in other class, I don't want that method to make any changes to this object. Even if it does, I don't want the changes to be affected to the original object created in the calling class.
Here is my sample code.
public final class Employee {
int employeeId;
public int getId() {
return employeeId;
}
public void setId(int id) {
this.employeeId = id;
}
}
public class Worker {
public static void process(Employee f, Employee g){
int c = f.getId();
f.setId(g.getId());
g.setId(c);
}
}
public class ImmutabilityTest{
public static void main(String[] args) {
Employee teamMember = new Employee();
Employee teamLead = new Employee();
teamMember.setId(5);
teamLead.setId(10);
System.out.println("Before process "+teamMember.getId() + " " + teamLead.getId());
Worker.process(teamMember, teamLead);
System.out.println("After process "+teamMember.getId() + " " + teamLead.getId());
}
}
The output will be
Before process 5 10
After process 10 5
Is there any way to avoid the change in the values of the member variables of the Employee class ? (apart from making them final)If not then how are we actually exploiting the Immutability property in java in user defined class ?
Any suggestions/opinions/pointers are appreciated ! Thanks..
Immutability is not a property in Java that can be applied to an Object with a single keyword, its a strategy that needs to be implemented on a case by case basis. Generally speaking, you utilize the final keyword and cloning in order to accomplish this. Note that the deeper your object nesting, the greater the level of difficulty in achieving true object immutability.
Here is a (more) immutable version of your Employee class:
public class Employee {
final int employeeId;
public Employee(final int id) {
super();
this.employeeId = id;
}
public int getId() {
return employeeId;
}
}
Note that reflection in Java makes it practically impossible to achieve true immutability, even with the use of the final instance variables and cloning.
Employee has a setter and has a non-private field, therefore it is not immutable.
Remove the setter, and make the field private, and your problem is solved.
Your other option is to pass a copy of the object (typically using a copy constructor to create it)
Applying the final keyword to a class simply indicates that the class can not be extended (or sub-classed).
It has nothing to do with whether or not its members can be modified.
You could change the visibility of the setId method to be package private, and make sure that Worker is in a different package to Employee.
Alternatively remove the setId method entirely.
[If the other class makes changes] I don't want the changes to be affected to the original object created in the calling class.
If you want to take that approach, then you need to create and pass a copy of the original object.
Note that unless you declare the private employeeId field to be final, you won't get the full benefit of immutability. Strictly speaking, the getId method needs to be synchronized if there is any possibility that different threads will call getId on the same Employee instance.
If you Don't want someone to change your properties value, you can keep them as private without setter.

Set and Get Methods in java?

How can I use the set and get methods, and why should I use them? Are they really helpful? And also can you give me examples of set and get methods?
Set and Get methods are a pattern of data encapsulation. Instead of accessing class member variables directly, you define get methods to access these variables, and set methods to modify them. By encapsulating them in this manner, you have control over the public interface, should you need to change the inner workings of the class in the future.
For example, for a member variable:
Integer x;
You might have methods:
Integer getX(){ return x; }
void setX(Integer x){ this.x = x; }
chiccodoro also mentioned an important point. If you only want to allow read access to the field for any foreign classes, you can do that by only providing a public get method and keeping the set private or not providing a set at all.
I want to add to other answers that setters can be used to prevent putting the object in an invalid state.
For instance let's suppose that I've to set a TaxId, modelled as a String. The first version of the setter can be as follows:
private String taxId;
public void setTaxId(String taxId) {
this.taxId = taxId;
}
However we'd better prevent the use to set the object with an invalid taxId, so we can introduce a check:
private String taxId;
public void setTaxId(String taxId) throws IllegalArgumentException {
if (isTaxIdValid(taxId)) {
throw new IllegalArgumentException("Tax Id '" + taxId + "' is invalid");
}
this.taxId = taxId;
}
The next step, to improve the modularity of the program, is to make the TaxId itself as an Object, able to check itself.
private final TaxId taxId = new TaxId()
public void setTaxId(String taxIdString) throws IllegalArgumentException {
taxId.set(taxIdString); //will throw exception if not valid
}
Similarly for the getter, what if we don't have a value yet? Maybe we want to have a different path, we could say:
public String getTaxId() throws IllegalStateException {
return taxId.get(); //will throw exception if not set
}
I think you want something like this:
public class Person {
private int age;
//public method to get the age variable
public int getAge(){
return this.age
}
//public method to set the age variable
public void setAge(int age){
this.age = age;
}
}
You're simply calling such a method on an object instance. Such methods are useful especially if setting something is supposed to have side effects. E.g. if you want to react to certain events like:
public void setAge(int age){
this.age = age;
double averageCigarettesPerYear = this.smokedCigarettes * 1.0 / age;
if(averageCigarettesPerYear >= 7300.0) {
this.eventBus.fire(new PersonSmokesTooMuchEvent(this));
}
}
Of course this can be dangerous if somebody forgets to call setAge(int) where he should and sets age directly using this.age.
Setters and getters are used to replace directly accessing member variables from external classes. if you use a setter and getter in accessing a property, you can include initialization, error checking, complex transformations, etc. Some examples:
private String x;
public void setX(String newX) {
if (newX == null) {
x = "";
} else {
x = newX;
}
}
public String getX() {
if (x == null) {
return "";
} else {
return x;
}
}
Having accessor methods is preferred to accessing fields directly, because it controls how fields are accessed (may impose data checking etc) and fits with interfaces (interfaces can not requires fields to be present, only methods).
Some benefits of using getters and setters (known as encapsulation or data-hiding):
(originally answered here)
1. The fields of a class can be made read-only (by only providing the getter) or write-only (by only providing the setter). This gives the class a total control of who gets to access/modify its fields.
Example:
class EncapsulationExample {
private int readOnly = -1; // this value can only be read, not altered
private int writeOnly = 0; // this value can only be changed, not viewed
public int getReadOnly() {
return readOnly;
}
public int setWriteOnly(int w) {
writeOnly = w;
}
}
2. The users of a class do not need to know how the class actually stores the data. This means data is separated and exists independently from the users thus allowing the code to be more easily modified and maintained. This allows the maintainers to make frequent changes like bug fixes, design and performance enhancements, all while not impacting users.
Furthermore, encapsulated resources are uniformly accessible to each user and have identical behavior independent of the user since this behavior is internally defined in the class.
Example (getting a value):
class EncapsulationExample {
private int value;
public int getValue() {
return value; // return the value
}
}
Now what if I wanted to return twice the value instead? I can just alter my getter and all the code that is using my example doesn't need to change and will get twice the value:
class EncapsulationExample {
private int value;
public int getValue() {
return value*2; // return twice the value
}
}
3. Makes the code cleaner, more readable and easier to comprehend.
Here is an example:
No encapsulation:
class Box {
int widthS; // width of the side
int widthT; // width of the top
// other stuff
}
// ...
Box b = new Box();
int w1 = b.widthS; // Hm... what is widthS again?
int w2 = b.widthT; // Don't mistake the names. I should make sure I use the proper variable here!
With encapsulation:
class Box {
private int widthS; // width of the side
private int widthT; // width of the top
public int getSideWidth() {
return widthS;
}
public int getTopWIdth() {
return widthT;
}
// other stuff
}
// ...
Box b = new Box();
int w1 = b.getSideWidth(); // Ok, this one gives me the width of the side
int w2 = b.getTopWidth(); // and this one gives me the width of the top. No confusion, whew!
Look how much more control you have on which information you are getting and how much clearer this is in the second example. Mind you, this example is trivial and in real-life the classes you would be dealing with a lot of resources being accessed by many different components. Thus, encapsulating the resources makes it clearer which ones we are accessing and in what way (getting or setting).
Here is good SO thread on this topic.
Here is good read on data encapsulation.
The above answers summarize the role of getters and setters better than I could, however I did want to add that your code should ideally be structured to reduce the use of pure getters and setters, i.e. those without complex constructions, validation, and so forth, as they break encapsulation. This doesn't mean you can't ever use them (stivlo's answer shows an example of a good use of getters and setters), just try to minimize how often you use them.
The problem is that getters and setters can act as a workaround for direct access of private data. Private data is called private because it's not meant to be shared with other objects; it's meant as a representation of the object's state. Allowing other objects to access an object's private fields defeats the entire purpose of setting it private in the first place. Moreover, you introduce coupling for every getter or setter you write. Consider this, for example:
private String foo;
public void setFoo(String bar) {
this.foo = bar;
}
What happens if, somewhere down the road, you decide you don't need foo anymore, or you want to make it an integer? Every object that uses the setFoo method now needs to be changed along with foo.
just because the OOP rule: Data Hiding and Encapsulation. It is a very bad practice to declare a object's as public and change it on the fly in most situations. Also there are many other reasons , but the root is Encapsulation in OOP. and "buy a book or go read on Object Oriented Programming ", you will understand everything on this after you read any book on OOP.
The benefits of get() set() methods are as follows ..
You can serialize you object easily.
You can create a persistent object from the containing class.
You can convert the properties to JSON easily.
In the DAO layer (Frameworks like Hibernate) you can directly save the object to DB.
Easy understanding of object oriented concept.
Needs in all design pattern except possibly in single tone pattern.
Security for properties protecting direct access.
Polymorphism, Encapsulation can be easily understood and implemented by this type of class.
Example:
private String personName;
private int personId;
public void setPersonName(String name) throws Exception{
if(!(name.equals("")||name=="")){
this.personName = name;
}
}
public String getPersonName(){
return this.personName;
}
public void setPersonId(int id) throws Exception{
this.personId = id;
}
public int getPersonId(){
return this.personId;
}
Above answers all assume that the object in question is an object with behaviour.
An advanced strategy in OOP is to separate data objects (that do zip, only have fields) and behaviour objects.
With data objects, it is perfectly fine to omit getters and instead have public fields. They usually don't have setters, since they most commonly are immutable - their fields are set via the constructors, and never again.
Have a look at Bob Martin's Clean Code or Pryce and Freeman's Growing OO Software... for details.
public class Person{
private int age;
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
i think this is you want..
and this also called pojo
this is the code for set method
public void setAge(int age){
this.age = age;
}
It looks like you trying to do something similar to C# if you want setAge create method setAge(int age){
this.age = age;}
I don't see a simple answer to the second question (why) here. So here goes.
Let's say you have a public field that gets used very often in your code. Whenever you decide you need to do something extra before you give or set this field you have a problem. You have to create a special getter and setter for this field and change your complete code from using the field directly to using the getter and setters.
Now imagine you are developing a library widely used by many people. When you need to make a change like the above and set direct access of the field to private the code of all the people using this field will break.
Using getters and setters is about future planning of the code, it makes it more flexible. Of course you can use public fields, especially for simple classes that just hold some data. But it's always a good idea to just make the field privately and code a get and set method for it.
This answer is merged from another question.
Your getAge() method is called instance method in Java.
To invoke an instance method, you should have a object of the Class in which this method is defined.
For Example, If this method in a Class called Person, then
Create a Person object using new operator
Person p = new Person();
To get the age of a Person object, use this method
p.getAge()
Although still a second year undergraduate student I will say my opinion. I believe that Java and private variables within your class are "RULES". Therefore because the variables in your class are private I think you use getters and setters to be able to define these variables outside the class.

Categories