as you can see the class below declares 2 private instance variables and 2 get & 2 set methods associated with each private member to allow for manipulation and validation of them.
My question is: which is better to use in the constructor deceleration, the instance variables directly as shown in the snippet below or to use the set methods associated with them and also which is promote good software practices to use in the toString method, the instance variables or their getter methods?
thank you for your time.
public Class Employee {
private String firstName;
private String lastName;
public Employee (String first, String last)
{
firstName = first;
lastName = last;
}//end of constructor
public void setFirstName(String first)
{
firstName = first;
}//end of method setFirstName
public String getFirstName()
{
return firstName;
}
public void setLastName(String last)
{
lastName = last;
}//end of method setLastName
public String getLastName()
{
return lastName;
}//end of method getLastName
public String toString()
{
return String.format ("%s: %s %s\n", "Employee Name: ", firstName, lastName);
}//end of method toString
}//end of class Employee
I tend to favour initialisation via construction. By using this method and providing appropriate checks (compilation time via final and runtime via null checks or similar) you can ensure your object is properly and completely instantiated.
Using the final keyword on your fields will make the compiler check that you've assigned a value to that field upon construction. It does mean that field is immutable, but it's surprising how often you require that.
I would be careful with providing getters for everything. If you're continually providing and using getters, that suggests that you're pulling data out of your object and manipulating it outside that object. Remember - a key principle of OO is getting objects to do things for you, rather than asking them for data and doing it yourself.
Rule #1, always limit the access to the least necessary, i.e. unless you explicitly need to change the values of the first/last names, make the object immutable (constructor with parameters, no setters only getters)
In general I tend to avoid calling non-static methods from the constructor (since the object isn't fully initialized at that stage). If the setter methods only sets a field to the parameter value, like above, I'd just set it in the constructor (i.e. not call the setter). If the setter is more complex, I'd try to factor out the logic to a static helper method, and use it both from the constructor and the setter methods. Something like:
int field_;
Constructor(int initialValue) {
field_ = helper(initialValue);
}
public void setField(int value) {
field_ = helper(value);
}
// not really complex, but avoid duplication of logic
private static int helper(int value) {
return 2*value;
}
If you expect your class to be extended (and the getter/setter overridden), it is best to use the methods instead of the variables.
NOTE: I'm not sure what happens exactly in the constructor, you are probably better off setting the variable directly.
You can mark the getter/setter as final and then you don't have to worry about overrides. Still a good practice to use those methods instead of direct access as you can put breakpoints or debug statements there more easily
I would use the setter. Sometimes you have extra code in the setters. For example, the setter for a list might also hook the list's Changed event, and by not using the setter, you will not capture the Changed event.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Stackoverflow is littered with articles on the purpose of private variables. Most of them say something to the effect that using private variables are 'safer'. Although, I have never found a truly concrete and satisfiable case of a private variable really making anything safer, besides maybe the fact that a user cannot accidentally modify a private variable from outside the class.
So what is the real extent to which a private variable is safer than a public variable? Does making a variable private simply protect code from your future self, and your fellow developers on the same project? Is it meant to protect it from other developers that are using your software as an API? Does the safety net which private variables provide extend as far as to prevent hackers and malicious users from changing highly important and sensitive parts of your code?
Encapsulation is about loose coupling:
The benefit of encapsulation is not to hide the values, or really to prevent direct access to them.
The benefit is to hide the implementation so that it does not become tightly coupled with the public interface.
This makes it safe to change the implementation because no client is relying on implementation details or side effects.
If you expose that you are using an ArrayList to store items, client code becomes coupled to the ArrayList implementation. You can not safely change it to a TreeSet because the implementation is part of the public interface. If the public interface was Collection then you can change the implementation because you only promise to provide a Collection semantics.
Same with things like storing say a instance in time as a long: if you want to change it to a java.util.Date or Calendar or JodaTime something then you can't, because every client is expecting a long if that implementation is public.
besides maybe the fact that a user cannot accidentally modify a private variable from outside the class
Well, that's already a benefit to start with.
The best thing with private variables, however, is that they are private for a reason; and that is, encapsulation.
You need to provide access to functionalities f1 and f2 for your class, and internally it relies on p1 and p2 which are private and should not be accessed so that your class can operate safely.
And that's all there is to it, really. Granting access to these variables to "outsiders" would compromise the safe operation of your class.
Sure, there are users with malicious intent who will use reflection to meddle with them, but they are not your primary target for your class, are they?
If "safer" is supposed to refer to security, then it's not really true. There are many ways to access an object's private variables.
If "safer" is meant to refer to robust code, meaning code that is less likely to hit exceptions or otherwise fail to work properly, then yes, it is safer. The benefit is that your class has total control over the value.
The simplest example is null values. Consider this class:
public class Person {
public String firstName;
public String lastName;
public List<Person> relatives;
}
If I want to write a method that accepts a Person instance, I have no guarantee that the fields are not null. I have to clutter my code with checks:
void populateFieldsWith(Person person) {
firstNameField.setText(person.firstName != null ? person.firstName : "");
lastNameField.setText(person.lastName != null ? person.lastName : "");
if (person.relatives != null) {
List<String> names = new ArrayList<>();
for (Person relative : person.relatives) {
if (relative != null
&& relative.firstName != null
&& relative.lastName != null) {
names.add(relative.firstName + " " + relative.lastName);
}
}
nameList.setData(names);
} else {
nameList.setData(Collections.emptyList());
}
}
If the fields are private, the Person class is the only class who can modify them, which gives the Person class the power to ensure they are non-null:
public class Person {
private String firstName;
private String lastName;
private final List<Person> relatives = new ArrayList<>();
/**
* Creates a new Person instance.
*
* #param firstName person's first name; cannot be null
* #param lastName person's last name; cannot be null
*
* #throws RuntimeException if any argument is null
*/
public Person(String firstName,
String lastName) {
setFirstName(firstName);
setLastName(lastName);
}
/**
* Returns this person's first name. This never returns null.
*/
public String getFirstName() {
return firstName;
}
/**
* Sets this person's first name.
*
* #param name new non-null first name
*
* #throws RuntimeException if any argument is null
*/
public void setFirstName(String name) {
Objects.requireNonNull(name, "Name cannot be null");
this.firstName = name;
}
/**
* Returns this person's last name. This never returns null.
*/
public String getLastName() {
return lastName;
}
/**
* Sets this person's last name.
*
* #param name new non-null last name
*
* #throws RuntimeException if any argument is null
*/
public void setLastName(String name) {
Objects.requireNonNull(name, "Name cannot be null");
this.lastName = name;
}
/**
* Returns a list of this person's relatives. This never returns null
* but it may return an empty list.
*/
public List<Person> getRelatives() {
return new ArrayList<Person>(relatives);
}
public void setRelatives(List<Person> relatives) {
Objects.requireNonNull(relatives, "List cannot be null");
for (Person person : relatives) {
Objects.requireNonNull(person, "List cannot contain null");
}
this.relatives.clear();
this.relatives.addAll(relatives);
}
public void addRelative(Person relative) {
Objects.requireNonNull(relative, "Person cannot be null");
this.relatives.add(relative);
}
}
Now we have a class that is unbreakable (unless someone uses reflection to get around the private access, but in that case you're dealing with malicious code and that enters the entirely different subject of runtime security).
There is no way firstName can be null, ever, because the only way any outside code can set it is to go through the setFirstName method, and that method will not allow the field to be set to a null value.
Now, let's return to the code that wanted to make use of a Person instance:
void populateFieldsWith(Person person) {
firstNameField.setText(person.getFirstName());
lastNameField.setText(person.getLastName());
List<String> names = new ArrayList<>();
for (Person relative : person.getRelatives()) {
names.add(relative.getFirstName() + " " + relative.getLastName());
}
nameList.setData(names);
}
The method no longer needs to be cluttered with checks for null. Programmers can safely assume that the value is not null, because the javadoc guarantees it. The guarantee is an honest one because there is no code path that can cause the method to return null.
Null values is just one use. The same setFirstName method could also check that the string is non-empty, check that it doesn't exceed a maximum length, check that it only contains certain types of characters, and so on, all so the getFirstName method can provide a guarantee via its javadoc to other programmers that it will return valid data.
Safer is a meaningless term used over and over. What all those books mean is that in terms of scalability on a big project, a private attribute should be considered as an entity univocally tied to a class so its value shall never be modified by other object in order to not alter its purpouse of existance (it's functionality). It's more a design matter than an implementation matter.
Think of an object which methods will return correct results only if their attributes are only modified by its very determinated methods: it couldn't guarantee that its method will return the expected result if an attribute is modified with a random value.
Furthermore, If you are coding an API library, the private elements won't be exposed in your binaries, making it more difficult to crack from a malicious user trying to instantiate objects not meant to be instantiated by the users.
After I have written a get method in a java class, is it better to use the get method in the same class or the variable itself?
For example:
if(a.getWidth()>this.getWidth())
or:
if(a.getWidth()>this.width)
Also I am confused if i should be using the this.anything so much. It seemed easier to read when comparing objects of the same type to each other.
is it better to use the get method in the same class or the variable
itself?
IMHO use the variable. Accessor methods are primarily for other objects to use.
Also I am confused if i should be using the this.anything so much. It
seemed easier to read when comparing objects of the same type to each
other.
It's not always required for you to explicitly use the this reference..it's mainly used for readability, like you said.
I think that using the getter methods are better for mantainability. Consider the Null Object pattern which a way to achieve is by making this:
public String getName(){
if (this.name == null){
this.name = "";
}
return this.name;
}
This should save you from checking up a lot of null before operating with the variable.
public boolean isCorrect(){
if(this.name != null && this.name.isEmpty()){
//The null check up is boilerplate code
return false;
}else{
return true;
}
}
I'd rather write this:
public boolean isCorrect(){
if(this.getName().isEmpty()){
//The null check up is boilerplate code
return false;
}else{
return true;
}
}
Of course, this depends if you adopt this pattern.
Also consider that you have
double width;
double height;
public double getWidth(){
return this.width;
}
but at some point you decide to change it for a class but still have the methods so your program doesn't break down.
Dimension dimension;
public double getWidth(){
return this.getDimension().getWidth();
}
// etc...
Finally (as commented by MadProgrammer), when you use inheritance, the methods can be overridden to represent better the intended object.
1) It may seem from inside a class that there is no difference between using field and getter but what if a getter is overridden by a subclass?
class A {
String name;
String address;
String getName() {
return name;
}
String getAddress() {
return address;
}
String getDescription() {
return name + " " + address;
}
}
class B extends A {
String country;
#Override
String getAddress() {
return super.getAddress() + ", " + country;
}
}
B.getDescription() is expected to return an extended address but it wouldnt. It would if A.getDescription() was implemented as
return getName() + " " + getAddress();
2) I personally dont use this for readability because IDE marks this with a different color
The use of this is not necessary unless you have a case (such as in a constructor) where a parameter has the same name as a field.
For accessing properties, it may be beneficial in the long run to use the public getters, because you may want to add some form of processing to the property, and if you use getters everywhere, you only have to make that change once.
If your get method returns the data with some formatting, you have to use the get method, otherwise, the variable itself will be fine to use.
this is only required if your method parameters are same as your member variables, otherwise, this is not compulsory.
For example:
private String str;
public void setString(String str){
this.str = str; // here this.str is necessary because this represents the memeber variable
}
public String getString(){
return this.str; // here this is optional and you can simply omit it
}
You can use either the accessor or the variable itself, its one of those personal preference things.
Some people like to use the variable itself because you don't have the overhead of calling a function. But, if you have any restrictions on the values your variables can be, sometimes it is just cleaner to only use your accessors and mutators; especially if you are going to be subclassing. But its one of those things that can go either way.
The way that I like to use the this keyword, is I always use it for instance variables. I find that it makes the code easier to read because you can visually determine where you are using instance variables, and where you are using local variables. Again this is a personal preference thing.
The main thing is to make sure your code is clean, and readable. Also, make sure that you are following whatever coding standard your organization is using, and be sure to be consistent.
In java, we prefer null object pattern than cluttering the code with not null check in all referencing. Recently we faced a problem over using null object by keeping a singleton object.
Assume we have Person class as below
public class Person {
public String firstName;
public String lastName;
public boolean isNull() {
return false;
}
public static final Person NULL = new Person() {
public boolean isNull() { return true; }
}
}
In this case, though I have declared NULL object as final, I can still modify the member variable and its available globally.
Person nullRef = Person.NULL;
Person.NULL.firstName = "sample";
System.out.println(nullRef.firstName);
In this case, its just three fields and I could solve mutability problem by overriding those three getter methods. But pratically there will be many fields which will be tough to override all corresponding getter methods.
Is there any standard pattern or strategy to solve this mutability issue in NULL objects?
Use Optional From Google Guava library
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
Quoting the library documentation:
Besides the increase in readability that comes from giving null a
name, the biggest advantage of Optional is its idiot-proof-ness
This is more natural way of dealing with null objects
Optional Google Guava
You need to have two levels of interface: One for the immutable part (only getters and immutable methods) and one for mutable parts that extends the immutable interface. Then the code needs to be refactored to only use the most restrictive interface possible in all relevant places.
So
public interface ImmutablePerson {
final String getFirstName();
}
public interface MutablePerson extends ImmutablePerson {
final void setLastName(final String newName);
}
Yes, now MutablePerson "is a" ImmutablePerson, but only when used as one :)
Additionally, the isNull check indicates that you need to think more about inversion of control.
To be concrete:
When you find yourself writing code like
if (!person.isNull()) {
person.setLastName("Foo");
}
You should instead just use your Null Object and think of it as a neutral element insted. Like so:
First:
final Person NullPerson = new Person() {
void setLastName(final String newName) {
// Do nothing, this is a neutral (Null) object
}
}
...and then later:
// Never need to check for isNull ever again - null objects just decide to ignore your request
person.setLastName("Foo");
You need to make all the fields "private" so that these are not accessible outside except for the getter code.
You need to modify "setter" methods and not the getter ones for making it immutable.
For eg.
public String setFirstName(String name){
if(!isNull()){
firstName = name;
}
}
Well, this is a very basic question, I've never coded in java, but I'm writing a class for a friend... Having something like:
class myClass{
private string name;
public string getName() {
return this.name;
}
public void setName (int newValue) {
this.name = newValue;
}
private int number;
public int getNumber() {
return this.number;
}
public void setNumber (int newValue) {
this.number = newValue;
}
}
The way I was thinking of building the constructor was:
public myClass (string name, int numbers) {
this.name = name;
this.number = number;
}
My questions:
I'm using the same identifiers for the properties as for the parameters. Does "this." avoid any trouble here?
Is it better to use the set methods and, if so, should i use "this."?
Thank you very much
Yes, it avoids the name clash. In the constructor's context, the name name refers to the parameter, and the name this.name refers to the instance field.
Depends on what you mean by "better." Personally, I would make the name and number fields final, so the class is immutable. In my experience, it's better to start from an immutable class definition, and only move towards something mutable if there is a legitimate need to do so.
Yes, this differentiates between an instance variable and a method parameter variable of the same name.
There's always debate on whether constructor or setter initialization is better. If you're only going to set the name and number when you first create the object, and won't need to update those variables later, just using the constructor and leaving out the setters is probably better. And yes, in the setter, you'd need to use this if your parameter has the same name as the field you want to set.
There's no problem having the parameter using the same name as the field; the this. explicitly disambiguates and the program will behave as intended.
Depending on your program it may or may not be advantageous to use setters instead of directly writing fields. If you write the values directly in the constructor, then you bypass any runtime checks that you might have in your setters, which could potentially cause your object to hold data it normally can't. On the other hand, if your setter tries to do something with the old value, then you probably don't want to call the setter because, in the constructor, there might not be a meaningful old value. I'd say it's not clearly better or worse to set the fields in the constructor than to use setters, so long as you're careful to avoid breaking the class invariants.
Yes. Using the this keyword avoids issues.
If there are logic in the get/set methods, then you should use them instead. Otherwise, setting the values in the constructor is valid.
1) When the object scope property is the same as the argument name you must use this to differentiate between them. When there is a name clash the local var or argument will take precedence over the property.
For this reason, I don't like to ever have the exact same name for each as it can easily lead to bugs.
2) I also would use the setters from within the constructor, because if there ever needs to be a validation or some other operation done on the argument at time of setting you'll only have to make the change in one place. Otherwise it is duplication and violates the DRY (Don't Repeat Yourself) principle.
I would do:
public myClass (string name, int number) {
setName( name );
setNumber( number );
}
Yes, this. avoids problems. Some people recommend that way, such as Rogue Wave in their book The Elements of Java Style.
Other common ways of dealing with this are:
name members with a "m" or "m_" prefix
private string m_name;
private int m_number;
public myClass(string name, int number) {
m_name = name;
m_number = number;
}
call the parameters a different name, usually a single letter or abbreviated version of the member name
private string name;
private int number;
public myClass(string nam, int num) {
name = nam;
number = num;
}
But I prefer the way you are using now with this.
This may sound very basic... can someone please explain the use of the toString() method and when to effectively use this?
Have done a search on google but could not find any good resource.
In most languages, toString or the equivalent method just guarantees that an object can be represented textually.
This is especially useful for logging, debugging, or any other circumstance where you need to be able to render any and every object you encounter as a string.
Objects often implement custom toString behavior so that the method actually tells you something about the object instance. For example, a Person class might override it to return "Last name, First name" while a Date class will show the date formatted according to some default setting (such as the current user interface culture).
There are several situations in which one would wish to override the toString method of a class (most of which are already mentioned in the existing answers), but one of the most common situations in which I have needed to explicitly call toString on an object is when using StringBuilder to construct a String.
public String createString(final String str) {
final StringBuilder sb = new StringBuilder(str);
sb.append("foo");
sb.append("bar");
return sb.toString();
}
You want to display an object and don't want to check if it is null before.
You want to concat Strings and not thinking about a special attribute, just provide a default one to the programmer.
Thus:
out.println("You are " + user);
will display "You are null" or "You are James" if user is null or toString displays "James" for this (existent) instance.
Assuming .NET or Java:
In general, you should overload ToString() when you want a textual representation of your class (assuming it makes sense for your class).
You can use toString() on an class by overriding it to provide some meaningful text representation of your object.
For example you may override toString() on a Person class to return the first and last name.
To string is should be used when you have a need to change a data type to a string. For built in types like int and such there string representations are what you expect. ie
int i = 5;
string s = i.ToString(); //s now equals "5"
Gives you the character string "5" for most complex types and all user created types you need to overload the tostring method or you will only get the name of the class. To string allows you to use the complex formating build into .net with your own objects. you can provide complex formatters like the datetime class does to give flexibility in using your own types.
toString() can be used to avoid the hexadecimal address, so to overcome this problem you need to override toString() then you will get original text format of data.
When you print reference variable then following task will happen.
if reference variable contains null then null value will be displayed.
if reference variable contains address of an object then toString() Method will be called by the JVM automatically.
By default toString() of Object.class will print:
ClassName#HexadecimalOfHashCode
You can override this method in your class to display some meaningful String.
Usually toString() method is used to print contents of an object.This method is already overridden in many java built-in class like String,StringBuffer,integer etc.
It used when we have to display the field values which we initialize through constructor and what to display without using any getter.
import Test.Date;
public class Employ {
private String firstname;
private String lastname;
private Date DOB;
private Date DOH;
public Employ(String name,String lastname,Date DOB,Date DOH)
{
this.firstname=name;
this.lastname=lastname;
this.DOB=DOB;
this.DOH=DOH;
}
public String toString(){
return String.format("%s %s Birthday %s Hired %s",firstname,lastname,DOB,DOH);
}
public static void main (String args[])
{
Date dob= new Date(12,3,1992);
Date doh= new Date(10,6,2005);
Employ em= new Employ("BOB", "Wrigh", dob,doh);
System.out.println(em);
}
}