I am writing a java program, that needs some final variables. The java class must be a singleton object. And I can't directly initialize the final variable. Here is my code:
public class Car {
private Price price = null;
//Constructor
public Car(Price p) {
this.price = p;
}
//method to get the singleton
private static Car instance = null;
public static Car getInstance(Price p) {
if(instance == null) {
instance = new ExcelUtil2(p);
}
return instance;
}
//declare & initialize final variable
private final Wheel WHEEL_TYPE = getWheelType();
//get value of the final variable
public Wheel getWheelType() {
Wheel wheel = Car.createWheel();
if(price.getAmount() > 30000){
wheel.setWheelType("Alloy");
}else{
wheel.setWheelType("Alluminium");
}
return wheel;
}
}
And I would like to know whether if I can do like this or not:
private final Wheel WHEEL_TYPE = getWheelType();
That is my first question.
And the next thing is, when I run it I am getting nullPointerException at:
price.getAmount()
in public Wheel getWheelType() method.
I am initializing price using a public constructor.
I am initilizing the class in some other class like this:
Car car = Car.getInstance(price);
Here I verified that both the price object and price.getAmount() are not null.
Can anyone guide me what am I doing wrong?
Thanks
There's nothing inherently wrong with
private final Wheel WHEEL_TYPE = getWheelType();
In general, though, (as recommended in the Java tutorial), when you do that you should be calling method that cannot be overridden—a final method, a static method, a private method, or a method in a final class.
However, with your particular code there is a problem. In the execution of getWheelType(), you are calling price.getAmount() and price gets initialized in the body of the constructor. Unfortunately for your design, field instance initializers are executed before the body of the constructor, so you will end up calling price.getAmount() before price is initialized.
I recommend that you simply move the assignment to WHEEL_TYPE to inside the constructor, after the assignment to price.
You are always allowed to initialize a final variable. The compiler
makes sure that you can do it only once.
Excerpt from an answer here: How final keyword works
As Ed mentioned, your price is an instance variable and it is used inside the instance method getWheelType(), which is OK. But the problem is this method is used to create a final variable. The final variable is assigned before the instance variable p is assigned.
If you really want to have your code structure, you may consider using a Builder pattern. My code is not well considered, but it will be something like this.
public class CarTwo {
private Price price = null;
private Builder b;
public Builder getBuilder(){
return b;
}
private final Wheel WHEEL_TYPE;
private CarTwo(Builder b) {
this.b = b;
this.price = b.getPrice();
WHEEL_TYPE = b.getWheelType();
}
private static CarTwo instance = null;
public static CarTwo getInstance(Builder builder) {
if(instance == null) {
instance = new ExcelUtil2(builder);
}
return instance;
}
public static class Builder{
private Price pr;
public Builder(Price price){
pr = price;
}
public Price getPrice(){
return pr;
}
public Wheel getWheelType() {
Wheel wheel = CarTwo.createWheel();
if(pr.getAmount() > 30000){
wheel.setWheelType("Alloy");
}else{
wheel.setWheelType("Alluminium");
}
return wheel;
}
}
}
Then, you can create the CarTwo object like this:
CarTwo.Builder b = new CarTwo.Builder(new Price());
CarTwo ct = CarTwo.getInstance(b);
Related
Error:
...
Caused by: java.lang.ExceptionInInitializerError
...
Caused by: java.lang.ClassCastException:
class com.evopulse.ds2150.TechTrees$BuildingTechTree
not an enum
at java.util.EnumSet.noneOf(Unknown Source)
at java.util.EnumSet.of(Unknown Source)
at com.evopulse.ds2150.TechTrees$BuildingTechTree.<clinit>(TechTrees.java:38)
Here is a snippet of my enumeration
public enum BuildingTechTree {
//Name SoftName Requirements
NONE ("NULL", null),
--> This next line is where it crashes
BARRACKS ("Barracks", EnumSet.of(NONE),
WALLS_SANDBAGS ("Sandbag wall", EnumSet.of(NONE),
POWERPLANT ("Power plant", EnumSet.of(BARRACKS)),
GUARDTOWER ("Guard Tower", EnumSet.of(BARRACKS));
Replacing EnumSet.of(NONE) and EnumSet.of(BARRACKS) with null, lets initialization work, but breaks my code, due to missing data structure... obviously, but I did it to test the rest of my code wasn't somehow the cause.
Removing EnumSet.of(NONE) and replacing with just NONE, and the same for BARRACKS, and changing all related variables, constructor, and methods, that didn't work either... (and even couldn't use the contains.all, since is wasn't "applicable to my changed variable"... )
I extended this example, using the second implementation:
https://gamedev.stackexchange.com/a/25652/48573
I also tried retracing my steps by copying the example verbatim. added
private static Set<BuildingTechTree> techsKnown;
techsKnown = (BuildingTechTree.BIODOME);
test = TechTrees.researchTech(techsKnown);
to another class to be called from for testing initialization. and had to change
public boolean researchTech(BuildingTechTree tech) {
to static
This resulted in the same "in not an enum" error. I don't have any rep, to comment on his answer to point out the initialization error...
Added info for both current answers, as both solutions cause the same new error:
public class TechTrees {
private static Set<BuildingTechTree> techsKnown;
public TechTrees() {
techsKnown = EnumSet.of(BuildingTechTree.NONE); //Using this
techsKnown = EnumSet.noneOf(BuildingTechTree.class); //Or this
}
public static boolean researchTech(BuildingTechTree tech) {
if (techsKnown.containsAll(tech.requirements)) { //Causes null pointer
return true; //exception # techsKnown
}
return false;
}
Your declaration structure is so clever it's a shame it doesn't work. But EnumSet apparently needs the enum to be fully initialized first. It tries to fetch the array of constants from the enum so that, among other things, it knows how much space is needed for its internal bitset.
Here's one workaround. It uses a helper method that creates an ordinary set (HashSet) first, and then, in a static initialization block, it iterates the enum constants and replaces all the sets with EnumSets.
public enum BuildingTechTree {
// Named constants
//Name SoftName Requirements
NONE ("NULL", null),
BARRACKS ("Barracks", setOf(NONE)),
WALLS_SANDBAGS ("Sandbag wall", setOf(NONE)),
POWERPLANT ("Power plant", setOf(BARRACKS)),
GUARDTOWER ("Guard Tower", setOf(BARRACKS));
private final String softName;
private Set<BuildingTechTree> requirements;
private BuildingTechTree(String softName, Set<BuildingTechTree> requirements) {
this.softName = softName;
this.requirements = requirements;
}
private static Set<BuildingTechTree> setOf(BuildingTechTree... values) {
return new HashSet<>(Arrays.asList(values));
}
static {
for (BuildingTechTree v : values()) {
if (v.requirements == null) {
v.requirements = EnumSet.noneOf(BuildingTechTree.class);
} else {
v.requirements = EnumSet.copyOf(v.requirements);
}
}
}
}
You have a chicken and egg problem. You could refactor your enum to something like this:
public enum BuildingTechTree {
NONE("NULL"),
BARRACKS("Barracks"),
WALLS_SANDBAGS("Sandbag wall"),
POWERPLANT("Power plant"),
GUARDTOWER("Guard Tower");
static {
NONE.trees = EnumSet.noneOf(BuildingTechTree.class);
BARRACKS.trees = EnumSet.of(NONE);
WALLS_SANDBAGS.trees = EnumSet.of(NONE);
POWERPLANT.trees = EnumSet.of(BARRACKS);
GUARDTOWER.trees = EnumSet.of(BARRACKS);
}
private String name;
private Set<BuildingTechTree> trees;
private BuildingTechTree(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Set<BuildingTechTree> getTrees() {
return Collections.unmodifiableSet(trees);
}
}
EDIT:
regarding your second problem: you're accessing a static variable, from a static method. But this variable is initialized when the constructor of the class has been called (which is a huge design problem). Don't use non-final static fields. And don't initialize static fields from instance methods or constructors. That doesn't make sense. You don't set the color that all cars should have when constructing a car. Initialize your static fields statically:
public class TechTrees {
private static final Set<BuildingTechTree> TECHS_KNOWN =
EnumSet.of(BuildingTechTree.NONE);
public static boolean researchTech(BuildingTechTree tech) {
return TECHS_KNOWN.containsAll(tech.requirements));
}
}
I have some doubts regarding how to do the following operation on a class that follow the Singleton model.
I have this original Singleton class:
public class ThreadsManager {
// I can have only one instance:
private final static ThreadsManager instance = new ThreadsManager();
// Private constructor:
private ThreadsManager() {
}
public static ThreadsManager getInstance(){
return instance;
}
}
Ok, this work well but now I have to modify it adding a new property (a String named userName) that have to be initialized when the singleton object is build and that
can not be changed at a later time
So I am trying to do something like it:
public class ThreadsManager {
private final static ThreadsManager instance = new ThreadsManager();
private final static String userName;
private ThreadsManager() {
}
public static ThreadsManager getInstance(String user){
userName = user;
return instance;
}
}
So I am trying to add the new String userName variable that is static (once for the class) and final (can not be changed at a second time)
My problem is that Eclips marks as an error the lines:
1) private final static String userName; saying to me that:
The blank final field userName may not have been initialized
It seems that would that the field will be initialized (I can initialize it to null but since it is final...I can't initialize later in the constructor)
2) userName = user; say to me that:
The final field ThreadsManager.userName cannot be assigned
So what is the best solution to handle this situation?
If I remove the final from the userName variable definition it seems to me that work well but then I can change this value but maybe I simply can not provide the setter method for this field so I prevent external changes....
Some ideas?
I think you want a singelton 'with arguments'. This should explain it :
Singleton with Arguments in Java
It is not going to be singleton if you want multiple state of an instance of that class,
you could create a cache of Object keyed with user so it would still be singleton for same state asked
private final Map<String, ThreadsManager> instanceCache = Collections.synchronizedMap<String, ThreadsManager>();
Also make sure you don't leak memory if you have tons of states for this class
Since this class is a Singleton then the name shouldn't really change too much. I would suggest just keeping it as a constant inside the class. If the name might change when the program is executed on different occasions then see Solution 2 below.
Solution 1:
public class ThreadsManager
{
private final static ThreadsManager instance = new ThreadsManager();
private String userName;
private ThreadsManager()
{
final String name = "Name";
userName = name;
}
public static synchronized ThreadsManager getInstance(String user)
{
return instance;
}
}
Solution 2:
If you really want to set the name of the Singleton and every time the program is execute the name might be different. Just add this method:
private String userName = null;
// Can only be set after Singleton is created and when userName is null.
public void setName(String n)
{
if(userName == null)
userName = n;
}
Don't make your getInstance() method have a parameter, that is a bad design. Every time someone, or you, tries to get an instance from your class they/you have to provide a parameter which will be 99% of the time be irrelevant.
You can do it using a nested class.
public class ThreadsManager {
private static String userName;
private ThreadsManager() {
}
public static ThreadsManager getInstance(String user){
if (userName == null)
userName = user;
// the holder's instance is only initialised at this point,
// after userName is set.
return Holder.instance;
}
static class Holder {
private final static ThreadsManager instance = new ThreadsManager();
}
}
First of all:
private final static String userName
may only be initialized inside the private constructor or during definition.
Secondly
You may end up with a null instance, so you might do something like this:
public class ThreadsManager {
private final static ThreadsManager instance = new ThreadsManager();
private String userName;
private ThreadsManager() {
}
private ThreadsManager(String user) {
userName = user;
}
public static ThreadsManager getInstance(String user){
if(instance == null) {
instance = new ThreadsManager(user);
} else {
Logger.getInstance().logWarning("User has already been set. Will continue with user ["+username+"].);
}
return instance;
}
}
The handling of how to deal with a second user name handed needs some thinking.
Overall you should try to keep the getInstance() method parameter free since it leads to the above mentioned problems.
How about
public class ThreadsManager {
private final static ThreadsManager instance = new ThreadsManager();
private static String userName;
public static synchronized ThreadsManager getInstance( String user ) {
if ( username == null ) { userName = user; }
return instance;
}
That would ensure userName is only set the first time.
It is, however, potentially very confusing semantics for a singleton to take a parameter that is ignored on subsequent getInstance()'s - possibly even race-condition-prone, depending on your use-case.
Cheers,
So I have this Contructor:
public MyClass(boolean done, int lvl , String s, int x, int y, Skill parent, Item item, int cost) {
this.done = done;
this.lvl = lvl;
this.name = s;
this.Xpos = x;
this.Ypos = y;
this.parent = parent;
this.item = item;
addSkill(this, s);
}
Is there a way for me to use/initialize this in another class without having to do
MyClass myclass = new MyClass(false, 0, "", 0, 0, null, this.item, 1)
If I just do
MyClass myclass;
Then I get the "horrid" null pointer exception.
It sounds like you want to create a second constructor that takes no parameters.
You can then write
MyClass myclass = new MyClass();
I recommend you implement something akin to the Builder Pattern. It is very versatile. You can read more about the Builder Pattern on Wikipedia.
MyClass myclass; is just a reference. You need to bind it with some object. No use of remote control without television. What else you can try to short your constructor is just provide a 0 parameter constructor.
public MyClass() {
this.done = "default";
this.lvl = "default value";
this.name = "default value";
this.Xpos = "default value";
this.Ypos = "default value";
this.parent = "default value";
this.item = "default value";
}
Now you can do like this MyClass mcRef=new MyClass();
It sounds like you might want some "default arguments". In Python, you could do something like this:
class MyClass:
def __init__(done=false, load=1, ...):
self.done = done
self.load = load
# ...
a_new_instance = MyClass(done=true)
Basically, all of your variables start out with a default value - but you can change them if you are so inclined.
In Java, it is a little different:
class MyClass {
private boolean done = false; // Notice the default value for done will be false
// ... you would list (and instantiate!) the rest of your variables
public MyClass() {}
public MyClass(boolean done, int lvl, ...) {
this.done = done;
// ...
}
}
In this way, you are only forced to call the constructor if you want to change the default values. But what happens if you only want to change 1 or 2 values? Well, you could make new constructors:
public MyClass(boolean done) { this.done = done; }
public MyClass(boolean done, int lvl) { this.done = done; this.lvl = lvl; }
but this will quickly get out of hand!
So, to get around this, we can use a "builder" pattern. That will look something like this:
public class MyClass {
private boolean done;
private int lvl;
// Now the constructor is private and takes a builder.
private MyClass(MyClassBuilder builder) {
// ... and your variables come from the ones you will build.
this.done = builder.done;
this.lvl = builder.lvl;
// ...
}
public static class MyClassBuilder {
// The builder also has the same members.
private boolean done;
private int lvl;
// Notice that we return the builder, this allows us to chain calls.
public MyClassBuilder done(boolean isDone) {
this.done = isDone;
return this;
}
public MyClassBuilder level(int level) {
this.lvl = level;
}
// And a method to build the object.
public MyClass build() {
MyClass mc = new MyClass();
mc.done = this.done;
mc.lvl = this.lvl;
// ... copy over all your variables from the builder to the new class
return mc;
}
}
}
So, now when we want to instantiate a MyClass object we can do this:
MyClass mc = MyClassBuilder.done(false);
or, we can chain the calls:
MyClass mc2 = MyClassBuilder.done(true).level(4). // ... you can go on for a while
As an aside, sometimes having more than three or four variables in a class is a sign that the class is doing too much. If the class has more than one "responsibility", you should break it up into a few smaller classes. Then you won't need a builder class.
This is not C++. Default values for all references is null. If you do not use new, the object remains null.
There are several methods of initialization if you dislike multi-parameter constructors. You can have setters return this and chain initialization like:
Person p = new Person().setAge(18).setName("Tom").setHeight(175);
or even simply
Person p = new Person().age(18).name("Tom").height(175);
Such method is not very common but definitely is easy to read and difficult to make mistake with.
You can also use static factory methods, like
class Person {
private Person() {} // mark as private to force creation with static method
public static Person create() {
Person p = new Person();
//fill default values?
return p;
}
}
VERY new to Java, so I am feeling like a child right now. The joys of learning a new language I guess.
Here is my Invoice Class:
public class Invoice {
//member inits
private int numberOfInvoices = 0;
private String companyName;
private double amountDue;
private String chargeDate;
private static int invoiceNumber = 0;
//constructor
public Invoice(String _companyName, double _amountDue, String _chargeDate)
{
numberOfInvoices++;
companyName = _companyName;
amountDue = _amountDue;
chargeDate = _chargeDate;
invoiceNumber = numberOfInvoices;
}
//getters
public String getCompanyName()
{
return companyName;
}
public double getAmountDue()
{
return amountDue;
}
public String getChargeDate()
{
return chargeDate;
}
public int getInvoiceNumber()
{
invoiceNumber = numberOfInvoices + 1;
return invoiceNumber;
}
//setters
public void setCompanyName(String _companyName)
{
companyName = _companyName;
}
public void setAmountDue(double _amountDue)
{
amountDue = _amountDue;
}
public void setChargeDate(String _chargeDate)
{
chargeDate = _chargeDate;
}
//helpers
public int incrementInvoices()
{
return numberOfInvoices++;
}
}
And here is the main method where I am trying to create three of these invoices, but increment the invoice number each time a new one is created.
public class InvoiceCreator {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Invoice invoice1 = new Invoice("Amazing Software", 5000.00, "January 18, 2009");
System.out.println(invoice1);
Invoice invoice2 = new Invoice("Best Programs", 4000.00, "February 18, 2009");
System.out.println(invoice2);
Invoice invoice3 = new Invoice("Champion Code", 3000.00, "March 18, 2009");
System.out.println(invoice3);
}
}
I'm also new to the IDE (netbeans), but through debugging and looking at each of the classes I created, all the fields are being initialized correctly, but the invoiceNumber = 1 on every one of them.
What am I doing incorrectly here?
You need to use a static field to generate incremental invoice numbers, not store the individual invoice numbers.
Try this:
public class Invoice {
//member inits
private static int nextInvoiceNumber = 0;
private String companyName;
private double amountDue;
private String chargeDate;
private int invoiceNumber = 0;
//constructor
public Invoice(String _companyName, double _amountDue, String _chargeDate)
{
invoiceNumber = nextInvoiceNumber;
nextInvoiceNumber++;
companyName = _companyName;
amountDue = _amountDue;
chargeDate = _chargeDate;
}
....
Declare numberOfInvoices to be static, so that there is a single value for the entire class, rather than a separate value for each instance.
private static int numberOfInvoices = 0;
You declared invoiceNumber as static, but numberOfInvoices is not static. In your constructor you are incrementing the number of invoices - which, being non-static, is initialised to 0 every time you create an instance of it. Then you assign this value to your invoice number.
The simple fix for your case is to declare the numberOfInvoices as static and invoiceNumber as non static:
private static int numberOfInvoices = 0;
private int invoiceNumber;
then you'll get the desired behaviour.
At the same time, it's worth noting that this implementation is ok for the purpose of learning the language, however it will not work for a production system, because the number will still be reset to 0 when the application exits and is restarted. In a production system, you would want to keep this number in a database or external file somewhere. You would then need to ensure that it's incremented in a thread-safe manner. In a production system, your logic would be something like this:
private int invoiceNumber;
private Object sync;
public Invoice(...) {
synchronised(sync) {
invoiceNumber = loadLastInvoiceNumberFromStorage();
invoiceNumber++;
writeLastInvoiceNumberFromStorage(invoiceNumber);
}
...
}
numberOfInvoices should be static. invoiceNumber should not be static. And you should synchronize the access to this field. See also: What is the best way to increase number of locks?
numberOfInvoices isn't the static member.
You currently increment an instance property and set it to the static property.
I suspect you want the opposite.
You could use a static field numberOfInvoices in your class, and increment it in the constructor.
Then you could have a static getter for the field.
numberOfInvoices will always be 0 when a new object is created. So, everytime you increment it and assign it to invoiceNumber, invoiceNumber gets the value 1. Instead, why dont you directly increment invoiceNumber .
use
private static int numberOfInvoices = 0;
Reason:
Static variables are related to class while nonstatic variables are related to object. As in this case you are storing the count of the object of the class so this is related to class. Thus you have to store it as static variable ( also called class variable)
For more details see here
You should declare your numberOfInvoices member as a static member :
private static int numberOfInvoices = 0;
This way all Invoice instance will share this member. If you don't declare it each Invoice instance will have their own value.
In preparing for an interview, someone mentioned knowing how to make a class/method in java read-only. I've been doing a bit of searching, but haven't found anything really concrete.
Maybe this question is simpler to answer than I'm making it out to be, but what would be a way to make a class or method read-only in java?
The following code will ensure that your class is always READ ONLY, but if you find any loop hole, please post it here.
import java.io.Serializable;
final public class ImmutableClass implements Cloneable,Serializable {
private static final long serialVersionUID = 6488148163144293060L;
private static volatile ImmutableClass instance;
private ImmutableClass() {
// no-op
System.out.println("instance created : " + this.hashCode());
}
/**
* Lazy Instantiation
*
* #return
*/
public static ImmutableClass getInstance() {
if (instance == null) {
synchronized (ImmutableClass.class) {
System.out.println("aquired lock");
if (instance == null) {
instance = new ImmutableClass() {
};
}
System.out.println("released lock");
}
}
return instance;
}
public Object readResolve() {
System.out.println("readResolve()");
return getInstance();
}
#Override
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
The Read-only class means, we are talking about "IMMUTABLE" concept.
The following example depicts the same:
public class ImmutableString {
static String upcase(String s) {
return s.toUpperCase(); // here local variable s vanishes
// it return the value to a new String object
}
public static void main(String[] args) {
String s = new String("abc");
System.out.println(s); //abc
String s1 = upcase(s);
System.out.println(s1); //ABC
System.out.println(s); //abc
}
}
Lets Say you want a read only version of an object,
case 1: if your class contains fields which are not pointers to any other objects eg:
public class Person{
private String name;
//Getters n Setters
}
in this case, you can return a copy of this class, write a constructor that accepts Person, any one who wants to get a Person object will have a copy of this object so any Setter operations wont effect the original object(Strings are immutable)
Case 2: in case your object contains a pointer to another object or list or map
in this case make classes implement an interface which has only read-only methods(Getters) and wherever you are returning the object, change it to return this interface, so client will have access to only read-only methods
eg:
class Person implements ReadOnly{
String name;
.. assume pointers also in here
// Getter n Setters
public PersonReadOnly(){
return this;
}
}
interface PersonReadOnly {
public String getName();
}
Simple rule: Don't have any public fields and No public setter methods.
For example, see class below:
final class AReadOnlyClass
{
private int anInt;
public int GetAnInt()
{
return anInt;
}
}