I have an abstract class which is supposed to have an (int) attribute that can't be modified after initialization and is pre-set to 1; what is the best way to do it?
Should I make it final?
The requirement is that inside the class I will have one and only one constructor(with parameters), and no setters.
If so, how do I make it 1 by default if it's final and (I suppose) I'm going to initialize it in the constructor?
Thanks!
As a matter of fact your can even hard code it, if it will always be a constant value.
For example if your variable should always be 25 you can do something like this:
public abstract class Test
{
protected final int pressure = 25;
//Constructor
public Test()
{
// TODO Auto-generated constructor stub
}
}
But if you evaluate the value on runtime you need to set it with in the constructor of the Object:
public abstract class Test
{
protected final int pressure;
//Constructor
public Test(int pressure)
{
this.pressure = pressure;
}
}
Note that in this case the variable must not be assigned earlier!
The question, if a final variable should be used depends on it's purpose. A final variable can only be assigned once over it's entire lifetime. If you have to modify it in any kind you should not use it.
You could use constructor overloading to achive this. See the example:
public abstract class TestClass{
private final int otherParam;
private final int fixedParam;
public TestClass(final int otherParam){
this.otherParam = otherParam;
this.fixedParam = 1;
}
public TestClass(final int otherParam, final int fixedParam){
this.otherParam = otherParam;
this.fixedParam = fixedParam;
}
}
You should use a constructor with parameters to set your initial values. Then, as you say, don't create any setter, and be sure your fields are private, so that no one can access it.
This way, you will do what you want, having fields initialized but never change after that.
Related
In Java, I feel that using Private when declaring an attribute and not declaring a Setter method for it gives the same outcome as using Final when declaring the attribute, both allow the variable to stay constant.
If that is the case, what is the benefit of using Final in this scenario?
Even without a setter other methods in the class can change the attribute so it's a completely different concept.
Many would argue it's not a good thing to do (it adds "side effects" to your program) but it's still possible.
Assumed you are talking about variables, the keywords final and private define different characteristics.
The keyword final denies any changes to the variable and throws compilation errors when modified or changed. However, without specifying public or private, with the default package-private access modifier, it could be accessed by other classes in the same package once initialized (text with bold fonts are corrected by #charsofire and #MC Emperor).
On the other hand, the keyword private rejects the idea of being called by other classes, even in the same package. But it could be changed and modified by methods in the same class, even without setter or getter methods.
For example in the same class of the same package:
public class Student {
private int score;
final int id;
public Student(int id, int score) {
this.id = id;
this.score = score;
}
public void modifyGrade(int newScore) {
// Accepted
this.score += newScore;
}
public void modifyID(int id) {
// Rejected
this.id = id;
}
}
And in different class of the same package:
public class School {
public static void main(String[] args) {
Student student = new Student(0, 35);
// Accepted
System.out.println(student.id);
// Rejected
System.out.println(student.score);
// Accepted
student.modifyGrade(29);
// throws exception
student.id = 5;
// Not visible
student.score = 29;
}
}
Hope this answer helps you well,
and many thanks again to both #charsofire and #MC Emperor, who helped to clarify significantly in this answer.
The answer is Encapsulation
Consider this.
public class Point
{
int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
//no getters or setters needed, I can just modify or read x and y directly.
}
public class FinalPoint
{
public final Point point;
public FinalPoint(int x, int y)
{
this.point = new Point(x, y);
}
//no getters needed, I'll just read point since it is public
}
Right now, this FinalPoint has a final Point as an instance field. On the one hand, it means that that instance field cannot be reassigned. However, the fields of that instance field can definitely be reassigned.
For example.
FinalPoint p = new FinalPoint(1, 2);
p.point.x = 4; //I have now modified state! final did not protect us here
The final keyword is powerful, but it does not mean that your data is unchangeable. It only means that that surface level reference is unchangeable - it will force a reference to always point to the same object. That does not stop the object its pointing to from changing it's internal state as much as it wants. The only guarantee final makes is that you always be pointing at the same object.
Which brings us to encapsulation. Encapsulation was created to solve this exact problem and more.
Consider this.
public class EncapsulatedPoint
{
private Point point;
public EncapsulatedPoint(int x, int y)
{
this.point = new Point(x, y);
}
public int getX() { return this.point.x; }
public int getY() { return this.point.y; }
}
Now, because I have encapsulated Point and exposed only the data I can safely expose, I have protected myself from modification. It is impossible to change this object (without using reflection or other hacks the designers are actively removing). It truly is Immutable.
Of course, Encapsulation is not superior to using final. There is a time and a place for both. Knowing when and where allows you to make your software secure.
Private variables will never access from the outside of the class and Final will never change by taking input from the user.
Just a few questions:
1) If you have a super class Monster and you create a subclass that inherits its behaviour. Its it good practice to call super in every constructor in the subclass. What I have done below is call it once in the first overloaded constructor and in the second overloaded constructor I call the first using this(..) Is this the best practice?
2) Is it better to use the method calls i.e setHealthAid(10) to set the class fields of use assignment instead i.e.
mHealthAid = -1;
mHasInvisibleMode = false;
class snippet without the implementation of getters and setters to make this short.
public class Monster {
private int mStrength;
private int mScareFactor;
public Monster(int strength, int scareFactor) {
setStrength(strength);
setScareFactor(scareFactor);
}
/* Getters and setters */
}
public class BigBoss extends Monster {
private int mHealthAid;
private boolean mHasInvisibleMode;
public BigBoss(int strength, int scareFactor) {
super(strength, scareFactor);
setHealthAid(-1);
setHasInvisibleMode(false);
}
public BigBoss(int strength,
int scareFactor,
int healthAid,
boolean hasInvisibleMode) {
this(strength, scareFactor);
setHealthAid(healthAid);
setHasInvisibleMode(hasInvisibleMode);
}
/* Getters and setters */
}
Many thanks for any suggestions,
1) If you have a super class Monster and you create a subclass that
inherits its behaviour. Its it good practice to call super in every
constructor in the subclass. What I have done below is call it once in
the first overloaded constructor and in the second overloaded
constructor I call the first using this(..) Is this the best practice?
You should have one constructor, which takes all parameters required to properly instantiate class. In second constructor with fewer parameters, you should use this to invoke first constructor and should pass default values for the missing parameters. Like:
public BigBoss(int strength, int scareFactor) {
this(strength, scareFactor, -1, false);
}
//costructor with all required params to instantiate BigBoss properly
public BigBoss(int strength,
int scareFactor,
int healthAid,
boolean hasInvisibleMode) {
super(strength, scareFactor);
mHealthAid = healthAid;
mHasInvisibleMode = hasInvisibleMode;
}
2) Is it better to use the method calls i.e setHealthAid(10) to set
the class fields of use assignment instead
You can use setters of fields from within the same class to set properties. But since you are already in the same class, you should directly use property to set values ie.
mHealthAid = -1;
mHasInvisibleMode = false;
This makes code a bit concise and you get small performance gain as no method call is involved.
That will work but is kind of inefficient because you're calling the setHealthAid(...) and setHasInvisibleMode(...) method twice when the second constructor is used. What you can do instead is this:
public BigBoss(int strength, int scareFactor) {
this(strength, scareFactor, -1, false);
}
public BigBoss(int strength,
int scareFactor,
int healthAid,
boolean hasInvisibleMode) {
super(strength, scareFactor);
setHealthAid(healthAid);
setHasInvisibleMode(hasInvisibleMode);
}
I'm just starting my first steps with Java, learned all the basics but then found a problem with an enum I need, so forgive me, if the solution to my problem is something very obvious:
So I've got this enum and want to add a unique id to each instance counting from 0 upwards, but without having to add another parameter to each constructor calling (because this can later on lead to errors ofc).
public enum TerrainTile{
WATER(1), GRASSLAND(1), HILL(2), FORREST(2), BLANK(99);
private final int id;
private final int moveCost;
private boolean hidden = true;
private TerrainTile(int moveCost) {
this.moveCost = moveCost;
}
And I thought to just add a
static int nextID = 0;
and edit the constructor to
private TerrainTile(int moveCost) {
this.id = nextID++;
this.moveCost = moveCost;
}
But I get an error message that it can not refer to a static field inside the initializer.
Is there any workaround?
You can use the ordinal() method for it. It is based on the order in which the members are declared in the source-code and counted from zero. So I guess, exactly what you need.
Just a note:
You can get your original enum member from ordinal number by calling .values()[index]
example:
int hillOrdinal = TerrainTile.HILL.ordinal(); // 2
TerrainTile hill = TerrainTile.values()[hillOrdinal];
It sounds like you are trying to combine class features into an enum. I'd be particularly wary of non-final, non-static member fields in an enum declaration. The behaviour you want seems to be best served by using a TerrainTile class (possibly a flyweight if you truly want the single-instance-per-type behaviour) and a TerrainTileType (or TerrainTile.Type) enum. Something like this:
public class TerrainTile {
public enum Type {
WATER(1), GRASSLAND(1), HILL(2), FORREST(2), BLANK(-1);
public final int MOVE_COST;
private TerrainTile(int moveCost) {
this.MOVE_COST = moveCost;
}
public boolean isTraversable() {
return (MOVE_COST > 0);
}
}
private final Type type;
private final Image texture;
...
private TerrainTile(Type type) {
this.type = type;
}
private static final Map<Type, TerrainTile> tiles = new EnumMap<>();
static {
// instantiate one TerrainTile for each type and store into the tiles Map
for (Type type: Type.values()) {
// Eventually, also load tile textures or set Color in this step
tiles.put(type, new TerrainTile(type));
}
}
public static TerrainTile getTile(Type type) {
// return the reference to the TerrainTile of this type
return tiles.get(type);
}
...
}
Is it possible to set a value for a final attribute from a Private method called from the Constructor of that Object?
public class FinalTest {
private final Object a;
//Constructor
public FinalTest() {
setA();
}
private void setA() {
a = new Object;
}
}
For the above class, compiler gives me an error saying I can't set the value for 'a' from the method.
I understand that its not possible to set value for a final variable from outside a constructor, but in the above case, I am actually doing it in a way within the constructor. So why isn't this allowed?
It's not allowed because you could call setA() via some other non-constructor method later on which would violate the final protection. Since final is a compile time enforced operation, the compiler enforces final by forcing initialization to occur in constructors or in-line.
In your simple example, all looks good but if you later updated your class to something like the following, the problem become more obvious...
public class FinalTest {
private final Object a;
//Constructor
public FinalTest() {
setA();
}
private void setA() {
a = new Object;
}
public void doSomething() {
this.setA(); // not good because a is final
}
}
Just a note: The compiler has to assume the worst case scenario. By declaring an attribute "final", the compiler has to ensure that the attribute cannot be modified outside of the constructor.
In a case where the method is called using reflection (for example), the compiler would never see it, ever. It's a lot easier to prove something is possible than impossible, that is why the compiler works the way it does.
Final checking is done at compile time not at runtime time. In your case compiler can't be sure that setA would not be called from some other method.
Why do you need to set the value of final variable from a private method ?
You may do it in this way :
public class FinalTest {
private final Object a;
{
a=new Object();
}
//Constructor
public FinalTest() {
}
}
In this case the object will be initialized on every FinalTest initialization.
I'm making a banking model, and an Account class has an accountNumber field. The account number should never change, but I cannot set the field as final because this will prevent the constructor from setting it.
If it's not possible to do this, it doesn't matter. It's just for a CS assignment so I want to make sure I'm doing it the best way I can.
Would the best implementation be to just make the field and its setter method private?
The constructor can set it if it is marked as final e.g. the following is legal:
public class BankAccount {
private final int accountNumber;
public BankAccount(int accountNumber) {
this.accountNumber = accountNumber;
}
}
In fact if a field is marked as final but not initialised in its declaration then it must be set in all constructors.
If you do not put a public setter on the class then the account number can't be changed from outside the class but marking it as final will also prevent it (accidentally) being changed by any methods inside the class.
If a variable is final it can (and must) be initialized in the constructor.
When a variable is final, it absolutely MUST be declared in the constructor, whether in the constructor or when you declare it. So worry not, you can create a final variable for your object, and then if you don't immediately set its value when you declare it, then you'll have to set its value in the constructor. So, technically speaking, both these codes are correct :
public class BankAccount {
private final int acctNumber;
public BankAccount(int acctNumber) {
this.acctNumber = acctNumber;
}
}
public class BankAccount {
private final int acctNumber = 12;
public BankAccount(int acctNumber) {
}
}
You can do this by doing something like private static final String accNumber = askAccNumber();
And then declare a function:
private static final String askAccNumber (){ //however you want to input your number }