How can I initialize a class without a constructor? - java

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;
}
}

Related

Constructor Chaining with subclasses in Java

Just a question RE: Constructor Chaining in subclasses that I can't find a good answer on and I'm confusing myself a bit with.
I'm making a basic little Text Based RPG for some practice and I'm going through my constructors for an abstract class and have the constructors from 0-4 params chained together like below
abstract class Creature {
// Fields
private String name;
private int lifeForce;
private int strength;
private int agility;
// Constructors + Chaining
public Creature() {
this("Unknown")
}
public Creature(String name) {
this(name, 100);
}
public Creature(String name, int lifeForce) {
this(name, lifeForce, 10);
}
public Creature(String name, int lifeForce, int strength) {
this(name, lifeForce, strength, 10);
}
public Creature(String name, int lifeForce, int strength, int agility) {
this.name = name;
this.lifeForce = lifeForce;
this.strength = strength;
this.agility = agility;
}
My confusion is how best to format the constructors of a subclass of creature, for example this simple Person class introduces two new fields. There's definitely too much repetition if I write the constructors like this
// Constructors + Chaining
public Person() {
super("Unknown");
this.skillClass=new Mage();
this.dialogue="...";
}
public Person(String name) {
super(name);
this.skillClass=new Mage();
this.dialogue="...";
} etc etc etc
I suppose I could restrict the constructors to limit the repetition but I'm mostly just wondering if there's good best practice that I'm missing here.
Any and all suggestions welcome and if anyone has any good resources to recommend that go deeper than the usual
Class B extends Class A
examples I'd massively appreciate.
In situations like this one when you need to use multiple constructors with different parameters, it is recommended to use the builder pattern like this :
abstract class Creature {
// Fields
private String name;
private int lifeForce;
private int strength;
private int agility;
private Creature(Builder<?> builder) {
this.name = builder.name;
this.lifeForce = builder.lifeForce;
// Add the other attributes here.
}
public static abstract Builder extends Builder<T extends Builder<T>> {
private String name;
private int lifeForce;
private int strength;
private int agility;
public Builder(//here you put the attributes that you need to have in all instances) {
// here you do the affectations.
}
// now you need to make the functions that set each property :
public Builder lifeForce(int lifeForce) {
this.lifeForce = lifeForce;
return this;
}
// you do the same thing for all the other attributes.
...
public Creature build() {
return new Creature(this);
}
}
}
So for the explanation : This pattern will allow you to create instances of your class by setting only the needed attributes.
As here you have subclasses the builder pattern will be little bit more harder to understand but it is the perfect solution in such situation.
We need to apply the builder pattern also for every subclasse so let's do it for the person class :
public class Person extends Creature {
private int anotherField;
public Person(Builder builder) {
super(builder);
this.anotherField = anotherField;
}
public static Builder extends Creature.Builder<Builder> {
public Builder(//add the fieldHere if it is needed in all class instances) {
// if the field is not mandatory you can omit this constructor but you need to put the function below.
}
public Builder anotherField(int anotherField) {
this.anotherField = anotherField;
}
public Person build() {
return new Person(this);
}
}
Now let me show you how tricky is this solution :
1/ declare person with 2 fields :
Person p1 = Person.Builder().name("name").anotherField(0).build();
2/ declare another one with just one field
Person p2 = Person.Builder().agility(1000).build();
Remark : In these two examples, i supposed that your builders' constructors don't have parameters. If for example the name is mandatory field :
Person p3 = Person.Builder("name").anotherField(0).build();
I wish that you had the idea about using builder pattern.

Invoke method while creating an object

Guys please tell me what is the construction when I call method while creating an object?
for example: Person p = new Person().get.....
If you want to create an Instance of the Object with new and call the Method while creating that Object than you can call that Method in the Constructor of that Objects Class
class Person {
Person() {
method();
}
}
If you create your Object (Person) with this constructor the Method will be invoked.
If you want to call a Method after creating the Object.
Person person = new Person();
String name = person.getName();
or
String name = new Person().getName();
I guess patter Builder is what are you looking for
public class Computer {
//required parameters
private String HDD;
private String RAM;
//optional parameters
private boolean isGraphicsCardEnabled;
private boolean isBluetoothEnabled;
public String getHDD() {
return HDD;
}
public String getRAM() {
return RAM;
}
public boolean isGraphicsCardEnabled() {
return isGraphicsCardEnabled;
}
public boolean isBluetoothEnabled() {
return isBluetoothEnabled;
}
private Computer(ComputerBuilder builder) {
this.HDD=builder.HDD;
this.RAM=builder.RAM;
this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
this.isBluetoothEnabled=builder.isBluetoothEnabled;
}
Computer comp = new Computer.ComputerBuilder(
"500 GB", "2 GB").setBluetoothEnabled(true)
.setGraphicsCardEnabled(true).build();
The closest thing that comes to mind may be singleton, but it doesn't create new objects. Person p = Person().getInstance()?

Proper Constructors to Run all Methods in Java

I have this class and need to know which constructor is needed to create an object that may immediately use all its methods without error
public class Robot {
private boolean fuelEmpty = true;
private int roboID;
private String greeting;
private String securityProtocol;
//insert robot constructor here
public void destroyAllHumans(){
while (fuelEmpty == false) {
//robot begins to destroy all humans
}
}
public int getRoboID(){
return roboID;
}
public void greet(){
System.out.println(greeting);
}
public void setSecurityProtocol(String proto){
securityProtocol = proto;
}
}
For example should look like this:
public Robot(int id, String greet) {
roboID = id;
greeting = greet;
}
or this:
public Robot(int id, String greet) {
roboID = id;
greeting = greet;
fuelEmpty = false;
}
or:
public Robot(boolean full, int id, String greet, String proto) {
roboID = id;
greeting = greet;
fuelEmpty = full;
securityProtocol = proto;
}
Which of these (or something else different) is needed so that all the other methods can run without an error?
You can overload the constructor as much as you need, the important thing is
the object gets properly instantiated after you create a new one...
a way can be:
public Robot() {
this(false, 0, "", "");
}
public Robot(int id) {
this(false, id, "", "");
}
public Robot(boolean fuelEmpty, int roboID, String greeting, String securityProtocol) {
this.fuelEmpty = fuelEmpty;
this.roboID = roboID;
this.greeting = greeting;
this.securityProtocol = securityProtocol;
}
so look how all other constructors will at the end call internally the
public Robot(boolean fuelEmpty, int roboID, String greeting, String securityProtocol)
that will give you the waranty that no matter which constructor is invoked, the Robot is fully created and can invoke all those methods without crashing
The solution works like this:
you look at each of your methods
you check which fields each method is using
you check more closely, if the method breaks when that field has its default value (like null for Objects, or false for booleans)
When you do that for all methods, you get a list of those fields that you need to initialize somehow. Then you could go forward and define a corresponding constructor.
But of course, that is the wrong approach.
The real answer goes like this: you don't put fields into a class because you can. You add them because they are required so that this class can implement the requirements (responsibilities) that you want it to implement. Meaning: you focus on the methods that your class should provide. Then you clarify which fields you need in order to implement these methods.
In other words: you have exactly those fields in your class that your class needs. If you have fields in there that go unused - then you get rid of them.

Can I initialize final variables by calling the class methods?

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);

Using reflection to get a specific attribute from a extended instance

I would like to make a generic method to get a List from the parameter object.
The problem is because I have a declared object with a instance of the other class that extends the declared class.
I don't want to use the instanceof solution because the number of classes that extends LimitedValue can be big.
I thought to use reflection for a solution, but I don't know how to use that with an instance of object, in this part of the code:
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
This is my full code:
public class CalculatorLimitedValue {
public static void main(String[] args) throws Exception {
StoreItem storeItem = new StoreItem(1L, "Name of StoreItem", 50L);
List listOfStoreItems = new ArrayList();
listOfStoreItems.add(storeItem);
LimitedValue limitedValue0 = new Store(listOfStoreItems);
List firstList = calculator(limitedValue0);
//do something with the list
SupermarketItem supermarketItem = new SupermarketItem(1L, "Name of SupermarketItem", 21L);
List listOfSupermarketItems = new ArrayList();
listOfSupermarketItems.add(supermarketItem);
LimitedValue limitedValue1 = new Supermarket(listOfSupermarketItems);
List secondList = calculator(limitedValue1);
//do something with the list
}
/** This is the method that I'd like to make generic to return a List */
private static List calculator(LimitedValue limitedValue) throws Exception{
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
/* I don't want to use this one way, because my classes that extends LimitedValue
can be big. I would like to made a generic way to get de list of classes. */
if (limitedValue instanceof Store) {
System.out.println("This is a store");
return ((Store) limitedValue).getStoreItems();
} else if (limitedValue instanceof Supermarket) {
System.out.println("This is a supermarket");
return ((Supermarket) limitedValue).getSupermarketItems();
}
return null;
}
}
If it help, these are my other classes:
LimitedValue.class
public class LimitedValue { }
StoreItem.class
public class StoreItem {
private Long id;
private String nameOfStoreItem;
private Long valueOfStoreItem;
public StoreItem(Long id, String nameOfStoreItem, Long valueOfStoreItem){
this.id = id;
this.nameOfStoreItem = nameOfStoreItem;
this.valueOfStoreItem = valueOfStoreItem;
}
//getters and setters...
}
SupermarketItem.class
public class SupermarketItem {
private Long id;
private String nameOfSupermarketItem;
private Long valueOfSupermarketItem;
public SupermarketItem() {
}
public SupermarketItem(Long id, String nameOfSupermarketItem, Long valueOfSupermarketItem) {
this.id = id;
this.nameOfSupermarketItem = nameOfSupermarketItem;
this.valueOfSupermarketItem = valueOfSupermarketItem;
}
//getters and setters...
}
Store.class
public class Store extends LimitedValue {
private List<StoreItem> storeItems;
public Store(List<StoreItem> storeItems) {
this.storeItems = storeItems;
}
//getters and setters
}
Supermarket.class
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
//getters and setters
}
You could try to use reflection here to try to achieve what you want, but it would be better to reconsider your overall design and try to use a better object oriented design that solves the problem at hand.
In particular, lets say we consider adding a method called getItems to the LimitedValue class that returns a List of items, which may be SupermarketItems or may be StoreItems. If it is structured correctly, you won't need to know the actual type because the code will be abstracted over it polymorphically.
public abstract class LimitedValue {
List<? extends Item> getItems();
}
We've now defined a new method on LimitedValue, but we also have to consider that we've introduced this new Item thing. I note that the SupermarketItem and StoreItem all share similiar attributes, name, id and value, so it seems that it might be possible to use a single class to represent them all.
public abstract class Item {
final Long id;
final String name;
final Long value;
public Item(final Long id, final Long name, final Long value) {
this.id = id;
this.name = name;
this.value = value;
}
String getName() {
return name;
}
// other getters and setters
}
public class SupermarketItem extends Item {
public SupermarketItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
public class StoreItem extends Item {
public StoreItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
Now we've completely abstracted away the need for any reflection when accessing these objects - you can simply call item.getValue() as you will know that every item in the list is of type Item.
Of course, you'll also need to refactor the Store and SuperMarket classes, for example:
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
public List<? extends Item> getItems() {
return supermarketItems;
}
}
and because you are only returning a List<Item> you always know what is in it, and you can change your main code to work with this.
This is a much cleaner long term solution.
To get the List value, use Method#invoke:
List list = method.invoke(limitedValue);
You don't need Object obj = cls.newInstance(); - you're not using it at all in the method.
In any case, you're making it very difficult for yourself. You could also define an interface
public interface HasList<E> {
List<E> getList();
}
and have all classes implement this.

Categories

Resources