I'm trying to create two objects of a Silo class in a SiloManager class, so that I can access both objects' methods. But I can't seem to make the SiloManager constructor work, nor to instance the classes properly. (I'm a beginner in java). Here's my code:
public class GrainSiloManager {
public GrainSilo silo1 = new GrainSilo(100);
public GrainSilo silo2 = new GrainSilo(50);
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = silo1;
this.silo2 = silo2;
}
private void showStatus() {
System.out.println("The current grain in silo1 is: " + silo1.getGrain());
System.out.println("The current grain in silo2 is: " + silo2.getGrain());
}
}
As I say i'm a beginnger so go easy heh, thanks for any help.
public GrainSilo silo1 = new GrainSilo(100);
public GrainSilo silo2 = new GrainSilo(50);
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = silo1;
this.silo2 = silo2;
}
This will get compiled as:
public GrainSilo silo1;
public GrainSilo silo2;
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = new GrainSilo(100);
this.silo2 = new GrainSilo(50);
this.silo1 = silo1;
this.silo2 = silo2;
}
which as you can see makes little to no sense. You're overwriting the object that you make, with the objects passed into the constructor.
Your constructor is going to replace the "public!" silo1 and silo2 objects with whatever is passed in. You could change your constructor like this
public GrainSiloManager() {
super();
}
or the even shorter (but equivalent)
public GrainSiloManager() {
}
And then call it like this
new GrainSiloManager().showStatus();
or you can use your existing approach (which will replace the GrainSoloManager.silo1 and GrainSoloManager.silo2 in your constructor)
GrainSilo silo1 = new GrainSilo(100);
GrainSilo silo2 = new GrainSilo(50);
new GrainSiloManager(silo1, silo2).showStatus();
Related
Why is this allowed:
import java.util.ArrayList;
public class BurgerClass {
private DefaultMenuClass defaultMenu;
ArrayList<String> burgerMenuItems = new ArrayList<String>();
public void displayBurgerMenu() {
burgerMenuItems = defaultMenu.getDefaultBurgerMenu();
for (String burger : burgerMenuItems) {
System.out.println(burger + "\n");
}
}
}
And this isn't:
import java.util.ArrayList;
public class BurgerClass {
private DefaultMenuClass defaultMenu;
ArrayList<String> burgerMenuItems = new ArrayList<String>();
burgerMenuItems = defaultMenu.getDefaultBurgerMenu(); //error here
public void displayBurgerMenu() {
for (String burger : burgerMenuItems) {
System.out.println(burger + "\n");
}
}
}
To answer the specific question, the reason why the first is "allowed" and the second isn't ——
Neither one is "allowed" or "disallowed"
In both cases, as Mureinik says, defaultMenu is never initialized. In the first case it doesn't matter, because displayBurgerMenu() is never called, so you never reach the line burgerMenuItems = defaultMenu.getDefaultBurgerMenu(); which would cause an error.
In the second case you do attempt to call it, at the line you've marked //error here so you get (I assume*) a NullPointerException.
Either way, you need to initialize defaultMenu to be something that is non-null before you attempt to call a method on it.
You need to do something along the lines of
private DefaultMenuClass defaultMenu = new DefaultMenuClass(<some-params?>);
or have some other way to get a DefaultMenuClass object. It's impossible to tell how that should happen given only the code you've presented in the question.
Separately, and not having anything to do with your error, it's pointless to do both
ArrayList<String> burgerMenuItems = new ArrayList<String>();
and then
burgerMenuItems = defaultMenu.getDefaultBurgerMenu();
You initialize burgerMenuItems to an empty ArrayList then you immediately throw that list away by setting burgerMenuItems to the list returned by .getDefaultBurgerMenu() (if there had been no error and something was returned)
* You really should say what error you are getting in your question, and not leave us to assume something.
#Data
#Builder
class BurgerClass {
private DefaultMenuClass defaultMenu;
public void displayBurgerMenu() {
List<String> burgerMenuItems = defaultMenu.getDefaultBurgerMenu();
for (String burger : burgerMenuItems) {
System.out.println(burger + "\n");
}
}
}
#Data
#Builder
class DefaultMenuClass {
List<String> defaultBurgerMenu;
public DefaultMenuClass(List<String> defaultBurgerMenu) {
this.defaultBurgerMenu = defaultBurgerMenu;
}
}
class Main {
public static void main(String[] args) {
BurgerClass obj = BurgerClass.builder().defaultMenu(DefaultMenuClass.builder().defaultBurgerMenu(Arrays.asList(new String[]{"Item1", "Item2"})).build()).build();
obj.displayBurgerMenu();
}
}
As you can able to see in above code,i am initialize all attribute of BurgerClass by providing builder pattern.
Also you can initialize dafaultMenu attributes using constructor. And while creating an instance of BurgerClass pass value of DefaultMenuClass.
public BurgerClass(DefaultMenuClass defaultMenu) {
this.defaultMenu = defaultMenu;
}
Just run above code, you will get an idea.
I'm coding a chess engine using bitboards and I wanna make an extensible API for the bitboards initializer, that would allow me to add more variants like chess960 in future.
So i came up with the following abstract superclass, which gives an uniform interface for all kind of initializers: it allocates the arrays used to store the bitboards and then calls the abstract method init() that has to be implemented by any subclass, inside there the bitboards should be created and assigned to the respective array
public abstract class BitboardInitializer {
private static final int NUMBER_OF_PLAYERS = 2;
protected long[] pawnsPositions, knightsPositions, bishopsPositions,
rooksPositions, queenPositions, kingPositions;
protected BitboardInitializer() {
pawnsPositions = knightsPositions = bishopsPositions =
rooksPositions = queenPositions = kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}
protected abstract void init();
public long getPawnsPositionsAs(int side) {
return pawnsPositions[side];
}
public long getKnightsPositionsAs(int side) {
return knightsPositions[side];
}
public long getBishopsPositionsAs(int side) {
return bishopsPositions[side];
}
public long getRooksPositionsAs(int side) {
return rooksPositions[side];
}
public long getQueenPositionsAs(int side) {
return queenPositions[side];
}
public long getKingPositionsAs(int side) {
return kingPositions[side];
}
}
An implementation to initialize standard chess bitboards, it simply assign the hard-coded bitboards values because standard chess starts always in one way. Side.White and Side.Black are two static final fields used as array indexes to avoid inconsistence. white = 0, black = 1:
public final class StandardChessInitializer extends BitboardInitializer {
public StandardChessInitializer() {
super();
}
protected void init() {
pawnsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_11111111_00000000L;
pawnsPositions[Side.BLACK] =
0b00000000_11111111_00000000_00000000_00000000_00000000_00000000_00000000L;
knightsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_01000010L;
knightsPositions[Side.BLACK] =
0b01000010_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
bishopsPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00100100L;
bishopsPositions[Side.BLACK] =
0b00100100_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
rooksPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_10000001L;
rooksPositions[Side.BLACK] =
0b10000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
queenPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00010000L;
queenPositions[Side.BLACK] =
0b00010000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
kingPositions[Side.WHITE] =
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00001000L;
kingPositions[Side.BLACK] =
0b00001000_00000000_00000000_00000000_00000000_00000000_00000000_00000000L;
}
}
The problem is that by calling any superclass' getter method I get binary 1000 for white (index 0) and 100000000000000000000000000000000000000000000000000000000000 for black (index 1) instead of the assigned values
An explanation of this strange behaviour would be highly appreciated, thanks in advance.
The problem is in the BitboardInitializer constructor, where you are initializing all of your array references to point to the same array:
protected BitboardInitializer() {
pawnsPositions = knightsPositions = bishopsPositions =
rooksPositions = queenPositions = kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}
Should be:
protected BitboardInitializer() {
pawnsPositions = new long[NUMBER_OF_PLAYERS];
knightsPositions = new long[NUMBER_OF_PLAYERS];
bishopsPositions = new long[NUMBER_OF_PLAYERS];
rooksPositions = new long[NUMBER_OF_PLAYERS];
queenPositions = new long[NUMBER_OF_PLAYERS];
kingPositions = new long[NUMBER_OF_PLAYERS];
init();
}
I am trying to brushup java after a long time.
Any help is much appreciated.
For demonstration I have Animal Class that has an array of innerclass of Organs.
public class Animal
{
String nameOfAnimal;
Organs [] vitalOrgans = new Organs[3];
public Animal()
{
}
public String getNameOfAnimal() {
return nameOfAnimal;
}
public void setNameOfAnimal(String nameOfAnimal) {
this.nameOfAnimal = nameOfAnimal;
}
#Override
public String toString() {
return "Animal{" + "nameOfAnimal=" + nameOfAnimal + "}";
}
class Organs{
String nameOfOrgan;
public String getNameOfOrgan() {
return nameOfOrgan;
}
public void setNameOfOrgan(String nameOfOrgan) {
this.nameOfOrgan = nameOfOrgan;
}
#Override
public String toString() {
return "Organs{" + "nameOfOrgan=" + nameOfOrgan + '}';
}
}
}
Now in driver file when I make call there is no syntactical error but I get "Exception in thread "main" java.lang.NoSuchFieldError: vitalOrgans"
Animal mamal = new Animal();
mamal.setNameOfAnimal("Chimp");
mamal.vitalOrgans[0].setNameOfOrgan("Heart");
System.out.println(mamal.vitalOrgans[0].getNameOfOrgan());
What would be the way to make this (or similar idea) to work.
Thanks.
You would need to initialize the vitalOrgrans with new Organs(). Like:
public Animal() {
for (int i = 0; i < vitalOrgans.length; i++) {
vitalOrgans[i] = new Organs();
}
}
Because when you say :
Organs[] vitalOrgans = new Organs[3];
You are creating an array of 3 null Organs. Hence the null pointer exception, when accessing "vitalOrgans[i].".
Taking the relevant bit of code:
public class Animal
{
//...
Organs [] vitalOrgans = new Organs[3];
//...
}
Since your declaration of vitalOrgans was never given an access modifier (i.e. one of private, public, protected) it took on default access, which means only other classes in the same package can see it. Since your other block of code is not in the same package, it cannot see the field.
A minimally viable modification to just make it work would be to set the access to public:
public class Animal
{
//...
public Organs [] vitalOrgans = new Organs[3];
//...
}
While this works, it's not necessarily the best solution, as if you ever change how vitalOrgans is represented, or need to perform any validation, those edits would have to be done throughout the application. Thus, a better solution (and also, a major stylistic convention in Java for those exact reasons) is to make it (and all your fields, in fact) private and access via methods:
public class Animal {
private String nameOfAnimal;
private Organs[] vitalOrgans = new Organs[3];
//...
public Organs[] getVitalOrgans() {
return vitalOrgans;
}
//Alternative accessor that fetches only one organ.
public Organs getVitalOrgan(int index) {
if(index >= 0 && index < vitalOrgans.length)
return vitalOrgans[index];
else
return null;
}
public void setVitalOrgans(Organs[] vitalOrgans) {
this.vitalOrgans = vitalOrgans
}
//...
}
Your caller could then access Organs via either form of the get method (note, you probably want Organs to be public):
Animal.Organs futureMammalHeart = mamal.getVitalOrgan(0); //Animal.Organs due to Organs being an inner class.
if(futureMammalHeart != null) //Demonstration of null check. Safety first!
futureMammalHeart.setNameOfOrgan("Heart");
Animal.Organs[] mammalianVitalOrgans = mamal.getVitalOrgans();
if(mammalianVitalOrgans != null) //Just in case...
System.out.println(mamal.mammalianVitalOrgans[0].getNameOfOrgan());
Also, as Ari mentioned in his answer, don't forget to initialize the organs in your array, otherwise you will get a NullPointerException!
Basically, i have a class where i have my arrays in, which is like this
public final class DepotDatabase {
private Driver[] arrayDrivers;
public DepotDatabase() {
arrayDrivers = new Driver[4];
arrayDrivers[0] = new Driver(1234, 1234, 0); // sample driver
arrayDrivers[1] = new Driver(4444, 4444, 0); // sample driver
arrayDrivers[2] = new Driver(1337, 1337, 1); // sample manager
arrayDrivers[3] = new Driver(1234, 1234, 0); // sample driver
}
and i want to print this array in another class, i did set up the array in another class
public Driver(int username, int password, int managerCheck) {
this.username = username;
this.password = password;
this.managerCheck = managerCheck;
}
but now i want to be able to print out all the drivers, but in another class which will be called ViewDrivers or something similar
You can create a method inside DepotDatabase to print the array, then create an object from and call print method.
public final class DepotDatabase {
private Driver[] arrayDrivers;
public void printArray() {
for (int i = 0; i < arrayDrivers.length; i++) {
Driver d = arrayDrivers[i];
System.out.println("Username : " + d.getUsername());
System.out.println("Password : " + d.getPassword());
System.out.println(" Manager Check: " + d.getManagerCheck());
}
}
the from the test class you can do:
public void execute() {
DepotDatabase ddb = new DepotDatabase();
ddb.printArray();
}
That's why you'll need to have getters and setters. You should have:
public Driver[] getDrivers() {
return arrayDrivers;
}
and in the other class, you simply call it (and print it or whatever).
Read this tutorial.
If you plan to print your array in another class you show create an accessor to it.
The common pattern for Java is to use "get plus name off attribute", getDrivers() you should also avoid the class name in such geter as it may changed due to application life.
public final class DepotDatabase {
//your code
public Driver[] getDrivers() {
return this.arrayDrivers;
}
}
Next question to answer is a returning the whole array is good idea. When you return it as above you loose control on it. And every one that call that method will be able to change the content of it.
To prevent this you should use so called Defensive copying
public Driver[] getDrivers() {
return Arrays.copyOf(arrayDrivers, arrayDrivers.length);
}
Then person will get an copy of it an will not harm your class.
The issue with this is that consumer of your class will have to call this method every time to get fresh list of cars.
To solve this issue you may want to user the [collection framework] where instead of array you cold define:
List<Driver> drivers new ArrayList<>();
and provide the drivers as [immutable] list
public Iterable<Driver> getDrivers() {
return java.util.Collections.unmodifiableList(drivers);
}
Iterable is an interface, that allow you to obtain an interator the the list consumer of class wold have possibility to traverse it. IF you wan to allow him to check that list contains some driver you can set the return type as Collection
class Storage {
private String items[] = new String[10];
public String[] getItems() {
return Arrays.copyOf(items, items.length);
}
}
class Store {
Storage storage = new Storage();
private void printStorage() {
String[] items = storage.getItems();
for (String item : items) {
}
}
}
I am used to use generics in typed collections, but I never actually used them to develop something.
I have several classes like this:
public class LogInfoWsClient extends GenericWsClient {
public void sendLogInfo(List<LogInfo> logInfoList) {
WebResource ws = super.getWebResource("/services/logInfo");
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<List<LogInfo>>(logInfoList) {
});
}
}
Where the only thing changing between one and another is the service String ("/services/info"), and the type of the list (LogInfo in this case)
I have refactored a couple of methods to a GenericWsClient class, but my objective would be to have something I can use like this:
List<LogInfo> myList = database.getList();
SuperGenericClient<List<LogInfo>> superClient = new SuperGenericClient<List<LogInfo>>();
superClient.send(myList,"/services/logInfo");
But I cannot figure out how to do it, or even if its possible. Would it be possible?
Yes it is possible infact if you look at java.util.collection package for example you will find all classes to be parameterzid.
So your class will be something like this
public SuperGenericClient<E> {
public E getSomething() {
return E;
}
}
Then to use it you will have
SuperGenericClient<String> myGenericClient = new SuperGenericClient<String>();
String something = myGenericClient.getSomething();
Extending your example itself your code will look like this:
public class SuperGenericClient<E> extends GenericWsClient {
public void send(List<E> entityList, String service) {
WebResource ws = super.getWebResource(service);
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<E>(entityList) {
});
}
}
}
public class GenericEntity<E> {
public GenericEntity(List<E> list){
}
}
You must read this for a very good understanding of Generics.
You could write your class like the one below - you can apply the same idea to GenericEntity.
public class SuperGenericClient<T> extends GenericWsClient {
public void send(List<T> list, String service) {
WebResource ws = super.getWebResource(service);
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<T>(list) {
});
}
}
}
You can then call it like that:
List<LogInfo> myList = database.getList();
SuperGenericClient<LogInfo> superClient = new SuperGenericClient<LogInfo>();
superClient.send(myList,"/services/logInfo");
Declare your class like this:
public class LogThing<T> {
public void sendLogInfo(List<T> list) {
// do thing!
}
}
And when you use it, do so like this:
List<LogInfo> myList = db.getList();
LogThing<LogInfo> superClient = new LogThing<LogInfo>();
superClient.sendLogInfo(myList);