This question already has answers here:
Immutable Type: public final fields vs. getter
(9 answers)
Closed 6 years ago.
I am aware that using getters and making fields private has many advantages in general cases (data-hiding, decoupling, blah, blah, blah). What I'm asking is related specifically to immutable classes.
Let's say I've created a model class to store the data from a REST response, for example:
public final class Profile {
private final int id;
private final String name;
private final String info;
private final String location;
private final URI avatar;
private final Gender gender;
// about 10 more fields
}
The class and its fields are all final and cannot be changed or overridden. Each field is an instance of an immutable class and is validated in the constructor. Also, every field needs to be publicly accessible (no data-hiding).
In such a case, what possible advantage could there be to tripling the size of the class to add getters for every field instead of just making the fields public?
Implementing the getters provides flexibility for future changes to the Profile class. If your class provides a getter you can change the underlying private member in the Profile class and it won't require changes to the consumers of your class. You do want to hide the data types of the class-level variables just as you want to hide the values.
Related
This question already has answers here:
Immutable Type: public final fields vs. getter
(9 answers)
Closed 6 years ago.
Is it recommended to have public access modifiers for the data fields in final (Immutable) java class, even if the data fields are not the references to mutable datatype Or Shall we access data fields directly as data fields are supposed to be defined in constructor itself hence nullify all chances of changing the internal representation of class.
Please suggest?
For example:
public class MainApp {
public static void main(String args[]) {
Immutablesample immutablesample = Immutablesample.getInstance("akkhil");
System.out.println(" Before modification " + immutablesample.getName());
immutablesample.name = "gupta";
System.out.println(" After modification " + immutablesample.getName());
}
}
is the calling code trying to change the data field by accessing it directly(without access modifier) for the following class:
public final class Immutablesample {
private final String name;
private Immutablesample(String name){
this.name = name;
}
public String getName(){
return name;
}
public static Immutablesample getInstance(String name){
return new Immutablesample(name);
}
}
How would it make the class prone to get its internal representation changed if i change the modifier from private to public
private String name; to public String name;
since the object was creating with parameterized constructor so has immutable data fields, than why is it necessary to make data fields private?
Two simple rules to follow:
Try to make your whole class as "immutable" as you can. For example setting private final fields only via constructors. And when using "incoming" collection objects, consider to create a copy of their content to be really on the safe side.
Keep in mind that good OO is about exposing behavior; not about exposing data. Meaning: you absolutely do not want to make fields public unless you have really good reasons to do so. In other words: you do not want that some other class B does something because of the content of some field in class A. And the way to prevent that: making your fields private!
In general, it's a bad decision to show your inner presentation of a class, so it's much better if you hide even final immutable fields. You can only show such as fields if your class it's something like a tuple, where all members are used from outside.
This question already has answers here:
Should I instantiate instance variables on declaration or in the constructor?
(15 answers)
Closed 7 years ago.
so let's say i have a class called city. what's the difference from where i initialize its fields? e.g.
public class City {
private String cityName;
private int population;
private boolean goodPeopleLiveThere;
City() {
cityName = "las vegas";
population = 603488;
goodPeopleLiveThere = true;
}
}
why would i initialize in the constructor rather than the fields or vice versa?
see the ambiguity i face is typically i would set them as parameters in the constructor and then initialize them in the main() when i instantiate my class, but then some tutorials i've seen used initialized them like aforementioned, and i'm yet to fully understand the implications of initialize in fields/constructor rather than in the object.
Usually, people use that format for functionality. Take the following for example
private int houseNumber;
private String houseStreet;
public House(int houseNumber, String houseStreet) {
this.houseNumber = houseNumber;
this.houseStreet = houseStreet;
}
Now this way, you can do things like the following much more easily.
public static void main(String[] args) {
House randomHouse = new House(12, "Main Street");
House otherHouse = new House(69, "Random Ave.");
}
instead of having to create a new class for each house.
There's no difference with these set variables. There may be a difference, however, if these variables depend on user input. For instance:
public class City{
private String cityName;
private int population;
private boolean goodPeopleLiveThere;
City(String city, int pop, boolean good)){
cityName = city;
population = pop;
goodPeopleLiveThere = good;
}
}
Now, in this example, a these variables rely on a value submitted upon instanciation, which is not at all rare when it comes to a constructor.
There is only a slight difference, besides personal preference. However, fields are initialized before constructor bodies are ran. This can cause errors if one it to override a field in the constructor that was initialized previously.
Most important is that one should be consistent throughout their code.
Initializing object-fields outside of the constructor is acceptable in some cases, for example, the builder-pattern is one of the static factory patterns that uses a nested class to initialize the instance members.
There's no "one better than the other" - simply different methods with pros and cons for each one of them.
When you initialize variables outside the constructor you should be careful not to publish the object before it's fully constructed otherwise you'll get yourself in a mess that will be difficult to debug.
The main objective is to avoid duplication of fields with best inheritance model on existing stuff:
I have following class hierarchy:
class A
{
private String fieldA1;
private String fieldA2
// getters and setters
}
Class B extends A
{
private String fieldB1;
private String fieldB2;
// getters and setters
}
A 'User' class will either extend A or B having its own fields.
Assume existing API's uses above data models.
Now there is a requirement to add new fields in Class A for new set of API's.
I have certain restriction not to modify existing data models since it exposes or breaks existing API's with these new fields . So new data models need to be created by extending existing ones such that new API's uses them with all existing fields + new fields. I have below solution which may not be the best approach as it adds duplication of fields.
class A
{
private String fieldA1;
private String fieldA2
// getters and setters
}
Class B extends A implements Common
{
private String fieldB1;
private String fieldB2;
// getters and setters
}
Class NewA extends A
{
private String fieldNewA;
// getters and setters
}
Class NewB extends NewA implements Common
{
private String fieldB1;
private String fieldB2;
private String fieldNewB;
// getters and setters
}
Interface Common
{
//marker interface
}
Please suggest if there is any better approach.
Thanks...
I think you need to take a step back and look at what is it that is causing you to keep adding new fields to your existing classes. Maybe you should just have one field which is a collection of property and values. This way any new field will just be another property/value in your collection. You won't have to then worry about adding new fields frequently.
Your example is not great, for example sub-classes cannot access private fields and it is not clear what you intend your subclasses to achieve.
If you wish to inherit state, your example should use either protected or public fields, or show getter and setter methods being inherited. When inheriting state, implementing an interface like Common is redundant. More detail may help clarify your intent.
That aside, yes you can extend your data models as you describe in order to add data types to an existing class. An example of wanting to do this might be wishing to create a Square class from a Triangle class, requiring adding a new point. And also requiring changing behaviour to make use of the new field.
I have been doing Java for 12 years, and I have recently been doing Javascript, and I was wondering if the Java community has considered some kind of flexible constructor mechanism.
Things can get messy with constructors in Java. If there are many different pathways to create an object, then you need a constructor for each.
What if you could have a constructor where you can put in whatever values you like that would match up with a classes internal field :
Person p = new Person([
name:’bob’,
height:123,
address:new Address([
street:’asdf’,
postcode:4232
])
]);
(I am using square brackets here, but you would need some other symbol, as this would conflict with arrays in Java)
Then you define which fields in a class may be used in a constructor combination with an annotation :
public class Person{
#constructable
private String name;
#constructable
private int height;
#constructable
Private Address address;
.....
}
public class Address {
#constructable
private String street;
#constructable
private String postcode;
#constructable
private String city;
.....
}
This would all be syntactic sugar. During compile time, the compiler would work out all the constructors that are needed for a class and update the class accordingly.
Has anything like this ever been proposed a JSR?
Does this break any core philosophy behind Java? (Ie. Constructors should not be so unrestrictive)
This can mostly be achieved by the Builder pattern. This is useful when there is a lot of information required to create the object.
I have reviewed Java.lang.String implementation.The constructor make me confused.
why result.value,result.count,result.offset can be used directly.
As the property of the three are just private!!!
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
public String(StringBuilder builder) {
String result = builder.toString();
this.value = result.value;
this.count = result.count;
this.offset = result.offset;
}
A Java method can access the private field values of any instance of the class that declares it. It is part of the language.
(Maybe you are thinking that "private" means the same thing in Java as it does in real life. It doesn't. The Java access modifiers are not primarily a mechanism for maintaining data privacy or security. What the access modifiers are primarily about is maintaining abstraction boundaries; i.e. preventing one class from depending on the internal implementation details of another class.)
result.value,result.count,result.offset come from the parameter builder
Private Access Modifier
Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself i.e by all its members.
Private access modifier is the most restrictive access level. Class and interfaces cannot be private.
Variables that are declared private can be accessed outside the class if public methods are present in the class which can retrieve the private entity of that class.