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 }
Related
I am trying to create a constructor that takes a field as a parameter, then puts it in a field that is stored in a superclass. Here is the code I am using
public crisps(String flavour, int quantity) {
this.flavour = super.getFlavour();
this.quantity = quantity;
}
In the superclass I have initialised the field with
private String flavour;
and I have an accessor method
public String getFlavour() {
return flavour;
}
I am getting an error "flavour has private access in the superclass", but I believe this shouldn't matter as I am calling the accessor method that returns it to the field?
What you should do:
Add a constructor to your super class:
public Superclass {
public SuperClass(String flavour) {
// super class constructor
this.flavour = flavour;
}
}
In the Crisps class:
public Crisps(String flavour, int quantity) {
super(flavour); // send flavour to the super class constructor
this.quantity = quantity;
}
Comments
Some comments to your question:
"In the superclass I have initialised the field with "
private String flavour;
This is not an initialization, it is a declaration. An initialization is when you set a value.
"I am getting an error " flavour has private access in the superclass" but I believe this shouldn't matter as I am calling the accessor method that returns it to the field?"
When you call a accessor (aka getter), it is ok - depends on the getter visibility.
The problem in you code is the:
this.flavour =
because flavour is not a field declared on Crisps class, but on the supper class, so you can't do a direct access like that. you should use my suggestion or declare a setter on the super class:
public void setFlavour(String flavour) {
this.flavour = flavour;
}
Then you can use it on the child class:
public Crisps(String flavour, int quantity) {
this.quantity = quantity;
super.setFlavour(flavour);
}
flavour is private. Although you're reading it from the public method, you're assigning it to a private field, and you likely didn't declare it in this class.
You could set flavour to protected in the parent class or define a setter for it
Ultimately your code doesn't really make sense though. Even if it did compile, it would be more or less: flavour = flavour. Perhaps you should rethink what you're trying to do a little bit
I think you may need a tighter grasp on Java and Object Oriented Programming.
http://docs.oracle.com/javase/tutorial/java/concepts/
You should start here.
public crisps(String flavour, int quantity)
{
super(flavour);
this.quantity = quantity;
}
This should work as see Docs
make
private String flavour;
public,otherwise your subclasses won't have access to this String.
Your superclass doesn't know about existence of any subclass. According to Java documentation, "private" makes any variable and method available within that class,where private variable or method was declared, no any class has access to it,even subclasses.
Once you chance your access modifier, you won't get any errors.
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.
I am wondering how do you access an argument created in a different class?
What I have:
public class Card {
private final int cardNumber;
private String cardName;
private final String cardOwner;
private final boolean isCredit;
private double balance;
public Card(int cardNumber, String cardName, String cardOwner, boolean isCredit, double balance) {
this.cardNumber = cardNumber;
this.cardName = cardName;
this.cardOwner = cardOwner;
...
}
I want to access the argument cardOwner in the following way:
public void add(Card[] newCards) {
if (cardOwner == owner) {
...
}
}
but I am not sure on how to go about doing that?
You can't access arguments outside the method they're in. Full stop.
What you can do is access the fields (which in your code have the same name as the constructor arguments. I recommend not giving different things the same name until you understand them well).
If you want to access the field cardOwner from inside the Card class, you can just use its name.
If you want to access the field cardOwner from outside the Card class, you will first need to decide which card you want to get the owner of. If you have a reference to a card (call it card), then you can use card.cardOwner to get that card's owner.
However, private members (fields/methods/constructors) can only be accessed from within the same class (that is the entire point of private). You could either make the field public instead, or add another way to access the field's value, such as a small public method:
public String getCardOwner() {
return cardOwner;
}
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);
}
...
}
As an example,
public class SwapNumbers {
private int aNumber = 0; ///////////////////////////////////
public SwapNumbers(){
}
public void changeNumber(int changed){
aNumber = changed;
}
public void swap(SwapNumbers otherNumber){ ///////////
aNumber = otherNumber.aNumber; //Can we access aNumber?
}
}
would the swap in this work? My first instinct was that it would not work because it is trying to access a private value.
Yes. making a member private means it is available to the current class along with any of its inner-classes, subject to static qualifiers.
Package-private (or the default, without any access modifiers) means it is available to any class in the same package.
the public modifier makes it available to any class in any package anywhere. Be careful with these :)
If you are within the same class, you will have no problems accessing any variables within the class--private, protected, or public.
You will only be unable to access private variables from outside
public class SwapNumber {
...
}