Cannot reference a variable before it is defined - Java - java

public class Wrapper {
public Wrapper(final String name, final String email) {
_name= name;
_email = email;
}
private static final Card testCard = new Card(_email, _name);
private final static String _name;
private final static String _email;
}
I would like the instantiate this class providing a name and an email.
I am getting "Cannot reference a variable before it is defined for (_email, _name) variables on line :
private static final Card testCard = new Card(_email, _name);
I can make it work by moving the declarations to the top but is there any other way?
Thanks

Based on your description, I don't think you want to use static.
I would like the instantiate this class providing a name and an email.
That means that you provide a name and an e-mail when creating an instance of the class. But using static means that there is only one name and one e-mail, that all instances of the class share! Unless every person in your universe has the same name and the same e-mail address, that is not what you want. So get rid of static on _name, _email, and testCard.
Also, initializing testCard outside the constructor won't work, because the program will try to do new Card(_email, _name) before _email and _name have been initialized. So change that to
private final Card testCard;
and in the constructor:
testCard = new Card(_email, _name);
after _email and _name have been set.
If you do this, you should be able to put the declarations anywhere you want. The "Cannot reference a variable before it is defined" or "Illegal forward reference" problems only come up when you have global (static) variables, according to this question.

You cann't initialize static field because variables _email and _name are not initialized yet. You should initialize testCard after _email and _name will be initialized.
For example, you can do it in constructor
public Wrapper(final String name, final String email)
{
_name= name;
_email = email;
testCard = new Card(_email, _name);
}
private static Card testCard;
or separate method for it
public static void initialize(String name, String email)
{
_name= name;
_email = email;
testCard = new Card(_email, _name);
}
Also you should remove final modifiers if you want to initialize static in contructor.

Related

why can't i use a field variable in a construction by referring this keyword [duplicate]

This question already has an answer here:
Why Cannot refer to instance fields while explicitly invoking a constructor java
(1 answer)
Closed 3 years ago.
I created my main use constructor with three parameter passed. the parameter above a default parameter. the goal is to set the first field which is name to be default assume user doesnt input a name. the problem come as for creditLimit and email i get the error below. why is this and what is it i do not understand? and what are the fixes.
- Cannot refer to an instance field creditLimit while explicitly invoking a
constructor
- Cannot refer to an instance field email while explicitly invoking a
public class VipCustomer {
private String name;
private int creditLimit;
private String email;
public VipCustomer()
{
this("Default",creditLimit,email);
}
public VipCustomer(String name, int creditLimit, String email) {
// TODO Auto-generated constructor stub
this.name = name;
this.creditLimit = creditLimit;
this.email = email;
}
public String getName()
{
return this.name;
}
public int getCreditLimit()
{
return creditLimit;
}
The Problem
There seems to be an issue with your first constructor which calls with second constructor with the following parameters at runtime:
this ("Default", 0, null);
This is because the values of creditLimit and email are not set.
creditLimit defaults to 0 as that is the default for ints.
email defaults to null because it is an empty object reference.
The Solution
To fix this issue, I recommend having some final fields at the top of your class that define default behavior.
public class VipCostumer {
// Change these values to what you would like.
public static final String DEFAULT_NAME = "Default";
public static final int DEFAULT_CREDIT = 100;
public static final String DEFAULT_EMAIL = "example#abc.com";
public VipCostumer() {
this(DEFAULT_NAME, DEFAULT_CREDIT, DEFAULT_EMAIL);
}
// rest of your code
}
Trade Off
While this may resolve your issue, I would recommend you consider whether or not you want to have defaults for something as specific as a costumer. Depending on your usage, you may want all costumer data to be differentiable, and creating a lot of a default costumers will take that ability away.
There is a problem with your first constructor, because it will call the second constructor (the one with the parameters), but you just try to set undefined variables to themselves.
If your goal is to set the first field which is name to be default assume user doesnt input a name, use this constructor
public VipCustomer()
{
this.name = "Default";
}
if creditLimit and email is a required value while name is not
public VipCustomer(int creditLimit, String email) {
this.name = "Default";
this.creditLimit = creditLimit;
this.email = email;
}

Changing a static variable with a static method [duplicate]

This question already has answers here:
Java - static variable and parameter with same name
(2 answers)
Closed 6 years ago.
I'm trying to change a private static variable with via a static method and BlueJ says that I can't because the variable I'm trying to change (which is declared as static) is non-static:
public class Playerinfo {
private static String name = ""; //Stores the name of the 'player'
public static void setname(String name) {
this.name = name;
}
}
The variable is called name and the method is called setname. I know that I can do this:
Playerinfo.name = (insert variable here)
I don't like the above because I wish to have the name variable in Playerinfo declared as private as not to be meddled with by other classes that easily.
There is no this inside a static method.
Your best bet is to rename the parameter of the method:
public class Playerinfo {
private static String name = ""; //Stores the name of the 'player'
public static void setname(String newName) {
name = newName;
}
}
this refers to a class instance, which is illegal in a static method. Either rename your parameter and do name = param;, or refer to it by class: Playerinfo.name = name;. Either way, it won't affect visibility to other classes.
As far as I understand name doesn't need to be static.Each PlayerInfo object must have its own name so remove static from both name and setname
public class Playerinfo{
private String name = ""; //Stores the name of the 'player'
public void setname(String newName){
this.name = newName;
}

calling a function containg enum in java

I have defined a class
class Prop{
public static enum property{
NAME,
CITY,
ADDRESS;
}
private String NAME;
private String CITY;
private String ADDRESS;
public String getValue(property pro){
switch(pro){
case NAME:
return NAME;
case CITY:
return CITY;}
return null;}
}
class CallPro{
private String name;
name=Prop.getValue("");
}
I am not exactly getting how to call getValue from class CallPro.
Basically what parameters should be passed to get the desired value.
I am a beginner in java
To run this program you need a public static void main(String[]) method first. That's your entry point into any Java program. Since, you want to assign the values inside callPro, add the main() method there.
Next, you want to call getProperty() which is an instance method belonging to class prop, so you'll need to create an instance of it first using the new constructor() syntax.
class callPro {
private static String name;
private static String city;
private static String address;
public static void main(String[] args) {
// create prop instance
prop property = new prop();
// call prop's method getValue()
name = property.getValue(prop.property.CITY);
city = property.getValue(prop.property.NAME);
address = property.getValue(prop.property.ADDRESS);
// New York, John, Central Park
System.out.println(name + ", " + city + ", " + address);
}
}
Notice, how I had to make callPro's members static to be able to access them inside the main() method because that's static too. Also, note how I referenced the Enums: className.enumType.enumValue.
To be able to see the values print from the main() method, you'll also need to provide values for your prop class members as
private String NAME = "John";
private String CITY = "New York";
private String ADDRESS = "Central Park";
public String getValue(property pro) {
switch (pro) {
case NAME:
return NAME;
case CITY:
return CITY;
case ADDRESS:
return ADDRESS;
}
return null;
}
Yes, you can loop through an enum's values and retrieve your properties in a loop as
prop property = new prop();
for (prop.property prop : prop.property.values()) {
System.out.println(property.getValue(prop));
}
enumType.values() returns an enumType[] of all enumValues which can be used with a for-each loop as shown above.

I got NullPointerException

I'm going back to OOP in java. Here I got problem with simple example:
class CreateString {
private String name;
public CreateString(String name) {
this.name = name;
}
String string = new String(name);//AAA
}
public class Main {
public static void main(String[] args) {
CreateString myName = new CreateString("tomjas");
}
}
I got NullPointerException from line denoted as "AAA". When I change the second line into
private String name="";
it's ok. What is wrong with that code? I thought that field is initialised as one could conclude from constructor. Any hints and pointers to documentation?
Your string variable is a class attribute. Therefore it will be initialized when your class instance is created. But at that time name is still null, as you only assign a value to name in the constructor. So you end up with a NullPointerException.
To fix it, move string = new String(name); into the constructor:
class CreateString {
private String name = null;
private String string = null;
public CreateString(String name) {
this.name = name;
string = new String(name);
}
}
As the constructor is only executed after all the attributes have been initialized, it doesn't matter where you put the line private String string;. You could also place it after the constructor (as you did), and it would still be fine.
All the fields are initialised before the constructor, as such when the line initialising string runs name is still null
class CreateString {
private String name; //<--runs first
public CreateString(String name) { //<--runs third
this.name = name;
}
String string = new String(name);//AAA <---runs second
}
You could move the string initialisation within the constructor to solve this
class CreateString {
private String name;
String String string;
public CreateString(String name) {
this.name = name;
string;= new String(name);//AAA
}
}
String string = new String(name);//AAA
That line is in initializer block.So the default value is null, Since you are using it before assigning some value. Move that line to constructor.
Since you dont have any base class defined for your class, the order of execution would be :
initialize member fields of this class.
run the constructor of this class.
Since while executing this
String string = new String(name);//AAA since it executes first.
the variable name is still null. That's why it throws NullPointerException

Initialize final variable before constructor in Java

Is there a solution to use a final variable in a Java constructor?
The problem is that if I initialize a final field like:
private final String name = "a name";
then I cannot use it in the constructor. Java first runs the constructor and then the fields. Is there a solution that allows me to access the final field in the constructor?
I do not really understand your question. That
public class Test3 {
private final String test = "test123";
public Test3() {
System.out.println("Test = "+test);
}
public static void main(String[] args) {
Test3 t = new Test3();
}
}
executes as follows:
$ javac Test3.java && java Test3
Test = test123
Do the initialization in the constructor, e.g.,
private final String name;
private YourObj() {
name = "a name";
}
Of course, if you actually know the value at variable declaration time, it makes more sense to make it a constant, e.g.,
private static final String NAME = "a name";
We're getting away from the question.
Yes, you can use a private final variable. For example:
public class Account {
private final String accountNumber;
private final String routingNumber;
public Account(String accountNumber, String routingNumber) {
this.accountNumber = accountNumber;
this.routingNumber = routingNumber;
}
}
What this means is that the Account class has a dependency on the two Strings, account and routing numbers. The values of these class attributes MUST be set when the Account class is constructed, and these number cannot be changed without creating a new class.
The 'final' modifier here makes the attributes immutable.
Marking it static, will allow you to use it in the constructor, but since you made it final, it can not be changed.
private static final String name = "a_name";
is is possible to use a static init block as well.
private static final String name;
static { name = "a_name"; }
If you are trying to modify the value in the constructor, then you can't assign a default value or you have to make it not final.
private String name = "a_name";
Foo( String name )
{
this.name = name;
}
or
private final String name;
Foo( String name )
{
if( s == null )
this.name = "a_name";
else
this.name = name;
}
In this case, you can mark the field as 'static' also.
Another possiblity is to initialize the field in an instance initializer blocK:
public class Foo {
final String bar;
{
System.out.println("initializing bar");
bar = "created at " + System.currentTimeMillis();
}
public Foo() {
System.out.println("in constructor. bar=" + bar);
}
public static void main(String[] args) {
new Foo();
}
}
In that case, you might as well make it static, too. And Java convention is to name such constants in ALL_CAPS.
private static final String name = getName();
where getName() is a static function that gets you the name.
I cannot use it in the constructor, while java first runs the constructor an then the fields...
This is not correct, fields are evaluated first, otherwise you couldn't access any default values of members in your constructors, since they would not be initialized. This does work:
public class A {
protected int member = 1;
public A() {
System.out.println(member);
}
}
The keyword final merely marks the member constant, it is treated as any other member otherwise.
EDIT: Are you trying to set the value in the constructor? That wouldn't work, since the member is immutable if defined as final.

Categories