I need to create array of references to child objects. In this case Room has to have array of references to objects: DarkRoom and LightRoom. Having error in line where initialization of array of type Room. What's missing?
public abstract class Room {
public Room[][] space = new Room[4][4]; // <<Syntax error on token ";",
space[0][0] = new DarkRoom();
space[0][1] = new LightRoom();
space[1][0] = new DarkRoom();
space[1][1] = new LightRoom();
}
public class LightRoom extends Room { ... }
public class DarkRoom extends Room { ... }
Your design is way off the mark. A class should not hold an array of child objects and in fact should have no knowledge about or dependence on its child classes. This is both a recursive and a logical nightmare.
I suggest you remove the array from within the Room class to somewhere more appropriate, such as the Hotel class or House class.
The initialization should not be done outside an initialization block or method, instead, do:
public Room[][] space = new Room[4][4];
{
space[0][0] = new DarkRoom();
space[0][1] = new LightRoom();
space[1][0] = new DarkRoom();
space[1][1] = new LightRoom();
}
It's complaining about the space[][] blocks. You can't just write code into your class definition.
public abstract class Room {
public Room[][] space = new Room[4][4]; // << error Syntax error on token ";",
public Room()
{
space[0][0] = new DarkRoom();
space[0][1] = new LightRoom();
space[1][0] = new DarkRoom();
space[1][1] = new LightRoom();
}
}
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.
Suppose I have classes Circle, Rectangle, and Triangle.
Based on input from a data file, I want to create the appropriate object. For instance, if the first line of shapes.dat is C.5 0 0, I will create a Circle object with radius 5. If the next line is R.5 3 0, I will create a Rectangle object with length 5 and width 3.
I know I could use basic if-else logic, but I was wondering whether there's a way to use the string as a means of instantiating a new object. Sort of like the exec() method in Python. Here's the code snippet describing what I want:
Scanner file = new Scanner (new File("shapes.dat"));
String s;
Map<Character,String> dict = new HashMap<Character,String>();
dict.put('C', "Circle");
dict.put('R', "Rectangle");
dict.put('T', "Triangle");
while (file.hasNextLine())
{
s = file.nextLine().trim();
String name = dict.get(s.toCharArray()[0]);
String data = s.split(".")[1];
String code = name + " x = new " + name + "(data);";
SYS.exec(code); //???
...
}
I'm not sure I understand correctly, seems weird no one else mentioned this yet:
Map<Character, ShapeFactory> dict = new HashMap<>();
dict.put('C', new CircleFactory());
dict.put('R', new RectangleFactory());
dict.put('T', new TriangleFactory());
...
ShapeFactory factory = dict.get(symbol);
Shape shape = factory.create(data);
You can make use of reflection to create instance dynamically.
String className = "com.shape.Triangle";
Class classDefinition = Class.forName(className);
Object obj = classDefinition.newInstance();
Or
Just use if-else to create instance of specific class.
Exec in Python executes code.
You can do the same thing with Java, for example with javassist.
You could read the data file, compile the statements and insert them in your own class.
But it seems overkill.
You could also use java reflection but it will produce a brittle and unclear code.
Instead if else if, I think that you should use abstraction and create a factory class by type of object.
It could look like :
Scanner file = new Scanner (new File("shapes.dat"));
String s;
Map<Character, ShapeBuilder> dict = new HashMap<Character,String>();
dict.put('C', new CircleBuilder());
dict.put('R', new RectangleBuilder());
dict.put('T', new TriangleBuilder());
while (file.hasNextLine()){
s = file.nextLine().trim();
char shapeSymbol = ...; // computed from s
ShapeBuilder builder = dict.get(shapeSymbol);
Shape shape = builder.build(s);
}
You can actually use polymorphism to avoid if-else statements. So, you can create objects that actually do those two jobs you want, match a line and create a shape. So you could use something like the following code.
public class Program {
public static void main() throws FileNotFoundException {
Scanner file = new Scanner(new File("shapes.dat"));
while (file.hasNextLine()) {
String line = file.nextLine().trim();
Shape shape = new Matches(
new RectangleMatch(),
new TriangleMatch(),
new SquareMatch(),
new CircleMatch()
).map(line);
}
}
public interface ShapeMatch {
boolean matches(String line);
Shape shape(String line);
}
public static final class RectangleMatch implements ShapeMatch {
#Override
public boolean matches(String line) {
return line.startsWith("R");
}
#Override
public Shape shape(String line) {
String[] dimensions = line.substring(2).split(" ");
return new Rectangle(
Integer.parseInt(dimensions[0]),
Integer.parseInt(dimensions[1]),
Integer.parseInt(dimensions[2])
);
}
}
public static final class CircleMatch implements ShapeMatch {
#Override
public boolean matches(String line) {
return line.startsWith("C");
}
#Override
public Shape shape(String line) {
return new Circle(Integer.parseInt(line.substring(2, line.indexOf(" "))));
}
}
public interface ShapeMapping {
Shape map(String line);
}
public static final class Matches implements ShapeMapping {
private final Iterable<ShapeMatch> matches;
public Matches(ShapeMatch... matches) {
this(Arrays.asList(matches));
}
public Matches(Iterable<ShapeMatch> matches) {
this.matches = matches;
}
#Override
public Shape map(String line) {
for (ShapeMatch match : matches) {
if (match.matches(line)) {
return match.shape(line);
}
}
throw new RuntimeException("Invalid shape entry line.");
}
}
}
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'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();
Can anyone tell me why this method is throwing an unchecked or unsafe exception? I understood that to happen when I try to edit the list I am iterating through... in the below, currentAdvanceTactics etc are not being iterated through at all.
public void tacticMeetsRequirements(ArrayList<Tactics> master) {
for (Tactics a : master) {
if (meetsrequirements(a)) {
if (a.movement.equals("Advance")) {
currentAdvanceTactics.add(a);
} else if (a.movement.equals("Retreat")) {
currentRetreatTactics.add(a);
} else if (a.movement.equals("Guard")) {
currentGuardTactics.add(a);
}
}
}
}
This is how the objects used in the master list are created:
for (int b = 0; b < numberoftactics; b++) {
tactic[b] = new Tactics(parsedTactics[b]);
tacticsMaster.add(tactic[b]);
}
parsedTactics is just raw data which gets read into the different variables.
tacticsMaster is declared as such:
public ArrayList<Tactics> tacticsMaster;
then later when I create the object it is contained within:
this.tacticsMaster = new ArrayList<Tactics>();
The currentAdvanceTactics list etc are all created as such:
public ArrayList currentGuardTactics = new ArrayList<Tactics>();
public ArrayList currentAdvanceTactics = new ArrayList<Tactics>();
public ArrayList currentRetreatTactics = new ArrayList<Tactics>();
Thanks in advance for any help!
You are using the raw version of the generic-type (ArrayList<T>). That's why you get the warning.
public ArrayList currentGuardTactics = new ArrayList<Tactics>();
public ArrayList currentAdvanceTactics = new ArrayList<Tactics>();
public ArrayList currentRetreatTactics = new ArrayList<Tactics>();
Try using the parameterized version -
public List<Tactics> currentGuardTactics = new ArrayList<Tactics>();
public List<Tactics> currentAdvanceTactics = new ArrayList<Tactics>();
public List<Tactics> currentRetreatTactics = new ArrayList<Tactics>();
The declaration of your ArrayLists are not type-safe. Change it to:
private ArrayList<Tactics> currentGuardTactics = new ArrayList<Tactics>();
private ArrayList<Tactics> currentAdvanceTactics = new ArrayList<Tactics>();
private ArrayList<Tactics> currentRetreatTactics = new ArrayList<Tactics>()
You should make the members also private. public declarations are usually not the best-practice way.