Well, I'm not sure if I can do this but let me ask the question anyway...
I got class Budynek which constructor is like this:
public Budynek(int numerBudynku)
{
this.id.nrBudynku = numerBudynku;
this.id.nrPietra = 0;
this.id.nrPokoju = 0;
}
so I am creating it like this:
Budynek Budynek1 = new Budynek(1);
Budynek Budynek2 = new Budynek(2);
Now I want to ask if there is any way to create a method that create new Budynek for me? Lets say if I use switch case, and case 1 will be "create new Budynek"
then I would like this method to do something like this
e.g licznik = 1
Budynek Budynek+licznik(so it will be Budynek1) = new Budynek(licznik)
then just licznik = licznik + 1;
is that possible?
You can create a List and store everything there, since your are indexing anyways with budynek+index
List<Budynek> budynekList = new ArrayList<Budynek>();
budynekList.add(new Budynek(10));
budynekList.add(new Budynek(20));
budynekList.add(new Budynek(400));
budynekList.get(index); // now you have your budynek objects with the given index.
As in the comments already pointed out, you can't declare variables on runtime.
Either
enum Budynek {
BUDYNEK_A,
BUDYNEK_B,
BUDYNEK_C;
public ID id;
private Budynek() {
this.id.nrBudynku = 1 + ordinal();
this.id.nrPietra = 0;
this.id.nrPokoju = 0;
}
}
Budynek.BUDY_A.id.nrBudynku
or you must go for an array:
Budynek[] budyneki = new Budynek[3];
...
budyneki[0].id.nrBudynku
budyneki[1].id.nrBudynku
budyneki[2].id.nrBudynku
Related
I am creating a game in java. I am using an array of Armor's for equipment
The issue, is that whenever I change 1 variable in my array, the other objects are also affected. This looks like a pointer issue but, all of the objects have been initialized as separate and called as new.
private Armor[] equip = new Armor[3];
public Inventory()
{
for(int i = 0; i<3;i++)
equip[i] = new Armor();
equip[0] = new Armor("head","You don't have head equipment","head",0,10,0,0);
equip[1] = new Armor("tunic","A simple farmers tunic","chest",0,10,0,0);
equip[2] = new Armor("baggy pants","Basic pants woven from rough cloth","legs",0,10,0,0);
System.out.println(armorDes(0));
System.out.println(armorDes(1));
System.out.println(armorDes(2));
}
All of the print lines output
baggy pants
0 armor
10 evasion bonus
Basic pants woven from rough cloth
instead of their own stats.
This was tested with a debugger and all of the objects are declared to different locations in data. Is this a java issue are am I just stupid?
Code is unclear above
private Armor[] equip = new Armor[3];
public Inventory()
{
for(int i = 0; i<3;i++)
equip[i] = new Armor();// Why creating object using default constructor here? no use
equip[0] = new Armor("head","You don't have head equipment","head",0,10,0,0);
equip[1] = new Armor("tunic","A simple farmers tunic","chest",0,10,0,0);
equip[2] = new Armor("baggy pants","Basic pants woven from rough cloth","legs",0,10,0,0);
// Use toString() method in Armour class to see the values present in variables.
//Also be sure all variables are instance variables
System.out.println(equip[0]);
System.out.println(equip[1]);
System.out.println(equip[2]);
//System.out.println(armorDes(0));
//System.out.println(armorDes(1));
//System.out.println(armorDes(2));
}
In the code below, I am trying to access the 'singleBuilding' variable inside the 'GMLWalker' visit function. I am getting the error "Cannot refer to the non-final local variable singleBuilding defined in an enclosing scope". Any clues on how I can achieve this.
private FeatureWalker IterateGroundSurface(BuildingClass singleBuilding){
FeatureWalker groundWalker = new FeatureWalker(){
public void visit(GroundSurface groundSurface){
GMLWalker gmlWalker = new GMLWalker(){
public void visit(LinearRing linearRing){
if(linearRing.isSetPosList()){
SurfaceMember surfaceMember = new SurfaceMember();
DirectPositionList posList = linearRing.getPosList();
List<Double> points = posList.toList3d();
List<CoordinateClass> polygonfloor = new ArrayList<CoordinateClass>();
PolygonClass poly = new PolygonClass();
for(int i=0 ; i<points.size() ;i+=3){
double[] vals = new double[]{points.get(i) , points.get(i+1),points.get(i+2)};
//System.out.println(vals[0]+" "+vals[1]+" "+vals[2]);
CoordinateClass coord = new CoordinateClass(vals);
polygonfloor.add(coord);
}
poly.setPolygon(polygonfloor);
surfaceMember.setPolygon(poly);
singleBuilding.setSurfacePolygon(surfaceMember);
//surfacePolygons.add(buildingSurfacePolygon);
}
}
};
groundSurface.accept(gmlWalker);
}
};
return groundWalker;
}
Thanks,
You need to make it final if you want to access it in a inner class. Again if you make it final then you won't be able to re initialize it.
private FeatureWalker IterateGroundSurface(final BuildingClass singleBuilding){
}
So I'm working on a project for my online AP Computer Science class and have run into a problem... Here's the original class definition I was given to build upon (stripped of code irrelevant to my question):
Note: The constructor of the Bin class accepts a single argument, a String. The String is representative of the Bin's name.
import java.util.*;
public class Warehouse
{
// Declare instance variables here
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
// Code that will start the warehouse
// off with 5 empty bins
}
public void addBin()
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
My job is to replace the areas commented out with actual code implementation. While the declaration of the instance variables is very straight forward, I'm rather torn on the best way to implement the code mentioned in the second comment.
In short, which is the best way to complete the above constructor?
Solution A:
private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
for(int i = 0; i < 5; i++)
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
Solution B:
private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
for(int i = 0; i < 5; i++)
{
addBin(); // <= Is this considered bad practice?
}
}
Solution C:
// Some magical wizard code I would have never thought of. XD
Thanks in advance!
Can you use Java 8?
final List<Bin> bins = IntStream.range(0, 5).
mapToObj(i -> new Bin("Bin" + i)).
collect(Collectors.toCollection(ArrayList::new));
Otherwise, both your solutions looks fine. I would prefer B as you already have an addBin method with one caveat. You must make addBin final as it is a public method. You should only call private or final methods from constructors otherwise you risk someone (possibly you) overriding that method in a subclass and then the subclasses method will be called from the superclass constructor before the subclass is initialized.
try to use a constant than magic numbers in code :)
import java.util.*;
public class Warehouse
{
// Declare instance variables here
private static final int INITIAL_BINS = 5;
private static final String DEFAULT_BINNAME = "DefaultBin_";
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( INITIAL_BINS );
for(int i = 0; i < INITIAL_BINS; i++)
{
myBins.add( new Bin( DEFAULT_BINNAME + i ) );
//addBin();// This is fine too depends on how flexible you want naming to be:)
}
}
public void addBin()
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
While I agree with most everything that's already been said, the java 8 functional programming style one-liner is pretty sexy. Magic numbers / strings should be avoided. If your class hasn't gone over functional style why not move the entire for loop into its own function? Generally the only thing that a constructor should do is initialize the state of your object. To make that explicit I try to keep to one line per member variable and that one line is nothing more than an initialization statement. IMO methods (which can reference the current state of the object) shouldn't be called from a constructor because your object hasn't been created yet. If you want to add functions to help you initialize your object, feel free to do so but keep them static so that the intent of the function (not referring to the state of the object) is clear.
...
private static final int INITIAL_BIN_COUNT = 5;
private static final String BIN_PREFIX = "B";
private final List<Bin> myBins;
public Warehouse(...) {
....
myBins = initMyBins();
}
private static List<Bin> initMyBins() {
final List<Bin> result = new ArrayList<Bin>(INITIAL_BIN_COUNT);
for(int i = 0; i < INITIAL_BIN_COUNT; i++) {
result.add(new Bin(BIN_PREFIX+i));
}
return result;
}
...
P.S. A few other notes, it's generally good practice to code to interface types rather than concrete class types (maybe you haven't covered interfaces yet, but that's what I did changing ArrayList to List.
I have a program in java that I wrote to return a table of values. Later on as the functions of this program grew I found that I would like to access a variable within the method that isn't returned but I am not sure the best way to go about it. I know that you cannot return more than one value but how would I go about accessing this variable without a major overhaul?
here is a simplified version of my code:
public class Reader {
public String[][] fluidigmReader(String cllmp) throws IOException {
//read in a file
while ((inpt = br.readLine()) != null) {
if (!inpt.equals("Calls")) {
continue;
}
break;
}
br.readLine();
inpt = br.readLine();
//set up parse parse parameters and parse
prse = inpt.split(dlmcma, -1);
while ((inpt = br.readLine()) != null) {
buffed.add(inpt);
}
int lncnt = 0;
String tbl[][] = new String[buffed.size()][rssnps.size()];
for (int s = 0; s < buffed.size(); s++) {
prse = buffed.get(s).split(dlmcma);
//turns out I want this smpls ArrayList elsewhere
smpls.add(prse[1]);
//making the table to search through
for (int m = 0; m < prse.length; m++) {
tbl[lncnt][m] = prse[m];
}
lncnt++;
}
//but I return just the tbl here
return tbl;
}
Can anyone recommend a way to use smpls in another class without returning it? Is this perhaps when you use a get/set sort of setup?
Sorry if this seems like an obvious question, I am still new to the world of modular programming
Right now you have this tbl variable. Wrap it in a class and add the list to the class.
class TableWrapper {
// default accessing for illustrative purposes -
// setters and getters are a good idea
String[][] table;
List<String> samples;
TableWrapper(String[][] table, List<String> samples) {
this.table = table;
this.samples = samples;
}
}
Then refactor your method to return the wrapper object.
public TableWrapper fluidigmReader(String cllmp) throws IOException {
// your code here
String tbl[][] = new String[buffed.size()][rssnps.size()];
TableWrapper tw = new TableWrapper(tbl,smpls);
// more of your code
return tw;
}
Then later in your code where you were going
String[][] tbl = fluidigmReader(cllmp);
You instead go
TableWrapper tw = fluidigmReader(cllmp);
String[][] tbl = tw.table;
List<String> smpls = tw.samples;
If you had used a dedicated class for the return value (such as the TableWrapper mentioned in another answer), then you could add additional fields there.
That is the good thing about classes - they can be extended. But you cannot extend String[][] in Java.
You can set a field, instead of a local variable, which you can retrieve later with a getter. You want to avoid it unless it is needed, but in this case it is.
You can use class(Inside Reader class) variable for this. But make sure that it's read/write is synchronized
I have a list of Nodes which I loop through:
for (int i = 0; i < aNodes.getLength(); i++) {
//
}
For example, assume the list contains 12 items, and that I know 3 items represent a row in a table, and the next 3 belong to the following row. That means my list of 12 Nodes originates from an HTML table containing 4 rows.
After each row I want to do something, for example, create a new object and populate it...or whatever. I have a solution:
ArrayList<Account> mAccounts = new ArrayList<Account>();
Account account = new Account();
for (int i = 0; i < aNodes.getLength(); i++) {
String nodeValue = aNodes.item(i).getNodeValue();
boolean isNewRow = (i % COLS_PER_ROW == 0);
if (isNewRow) {
account = new Account();
mAccounts.add(account);
}
switch (i % COLS_PER_ROW) {
case ACCOUNT_POS:
account.setAccount(nodeValue);
break;
case BALANCE_POS:
account.setBalance(nodeValue);
break;
case DATE_POS:
account.setDate(nodeValue);
break;
}
}
But there are numerous things I don't like about this solution:
An Account instance is created twice first time, once outside the loop and then once because a new row is detected.
It uses integer constants ACCOUNT_POS=0, BALANCE_POS=1, DATE_POS=2...this doesn't feel very nice and I think I should be using an enum.
I can't use an enum with the loop variable 'i'.
I can't use a for each loop since Nodes doesn't implement the correct interface,
Can anyone suggest a better way of doing this that solves the list of things I don't like about it?
Thank you.
You can increment i by COLS_PER_ROW instead of 1 and then write:
for (int i = 0; i < aNodes.getLength(); i += COLS_PER_ROW) {
account = new Account();
String account = aNodes.item(i).getNodeValue();
account.setAccount(account);
String balance = aNodes.item(i+1).getNodeValue();
account.setBalance(balance);
String date = aNodes.item(i+2).getNodeValue();
account.setDate(date);
mAccounts.add(account);
}
I can't use an enum with the loop variable 'i'.
No, but you can use:
for(SomeEnum item : SomeEnum.values()){
// code here
}
You're working with a position based file, so, if I understand you correctly, you've a structure which is organized as follows:
account;
balance,
date;
Knowing this, maybe you could better deal with the index in a while loop, rather than using a for loop, as follows:
int i = 0;
while (i < aNodes.getLength()) {
account = new Account();
account.setAccount(aNodes.item(i).getNodeValue());
account.setBalance(aNodes.item(i+1).getNodeValue());
account.setBalance(aNodes.item(i+2).getNodeValue());
mAccounts.add(account)
i += 3;
}
I would also suggest to extract the account-filling-code in a new method, like 'extractAccountFromNodes', and then call it inside the loop; so the loop could become:
int i = 0;
while (i < aNodes.getLength()) {
mAccount.add(extractAccountFromNodes(aNodes, i));
i += 3;
}
with the method extractAccountFromNodes like this:
private Account extractAccountFromNodes(Nodes nodes, int position) {
account = new Account();
account.setAccount(nodes.item(i).getNodeValue());
account.setBalance(nodes.item(i+1).getNodeValue());
account.setBalance(nodes.item(i+2).getNodeValue());
return account;
}