I have extended a class in hope to store a global array (make the array within the class be seen by another object) by using the set1sub(sub.local) method
public class BattleShipsClient extends ShipLocations implements Runnable, BattleShipConstants
{
BattleShipsClient()
{
}
public void placeBoard(int player) throws IOException// this is only called once and not updated when clicked again
{
while(getLocations())
{
while(isWaiting())//true
{
toServer.writeInt(player);
int row = getRowSelected();
int col = getColumnSelected();
int choice=Integer.parseInt(JOptionPane.showInputDialog("Please 1 for a sub, 2 for a battleship and 3 for a destroyer"));
clickCount ++;
if(clickCount >2)
{
setLocation(false);
continueToPlay=true;
}
if (choice ==1 &&sub.placed==false)
{
String orientation =JOptionPane.showInputDialog("please enter your orientations");
if(orientation.equalsIgnoreCase("h"))
{
//row os the same
//column number will be sent, then plus one on the other side
sub.local = new int[2][2];
sub.local[0][0] =row;
sub.local[0][1]=col;
sub.local[1][0]=row;
sub.local[1][1] =col+1;
toServer.writeInt(row);
toServer.writeInt(col);
toServer.writeChar('s');
sub.placed=true;
setp1sub(sub.local);
/*setp1sub(new int[][]{{row,col},
{row,col+1}});*/
grid[row][col+1].setToken(getMyToken());
}
I then have a ship Locations class however when i create a new object of the ship locations class and try to read this array it always is set to [[0, 0], [0, 0]], ive tried making it static and atomic
public class ShipLocations {
int [][] p1sub;
public ShipLocations()
{
p1sub = new int[2][2];
}
public int[][] getp1sub()
{
return p1sub;
}
public void setp1sub(int[][] local) {
for (int i = 0;i <local.length;i++)
{
for(int j = 0;j<local.length;j++)
{
p1sub [i][j]= local[i][j];
}
}
}
}
Whenever you create a new instance of ShipLocations(or a subclass) the constructor is called, which in your case, reinitializes the p1sub array.
In your design, you are overusing inheritance. You should not inherit from a class just to use its methods and variables.
To store a global variable in a class:
public class ShipLocations {
static int [][] p1sub;
static{
p1sub = new int[2][2];
}
public static void setp1sub(...){...}
public static int[][] getp1sub(){...}
}
And then use it by class name instead of creating instances:
int [][] x = ShipLocations.getp1sub();
Though the use of global variables shoud be avoided when possible. It is considered bad design and might be a problem when reusing the code.
The correct way of doing this is to have the ShipLocations object as a local variable in BattleShipsClient and set it when initializing new instance. You will then first create a common ShipLocation object and hand it to every client that should see the same array.
Related
I am a novice Java programmer trying to use classes defined in a different file. So, I've written these two .java files:
First, there's MyLibrary.java:
package mymainprogram;
public class MyLibrary {
public class MyRecord {
int number;
char letter;
}
public static int TriplePlusThree(int input_number) {
return ((input_number*3) + 3);
}
}
Then, MyMainProgram.java:
package mymainprogram;
import java.util.Scanner;
public class MyMainProgram {
public static void main(String[] args) {
Scanner keyread = new Scanner(System.in);
System.out.print("Enter Number to Process: ");
int num = keyread.nextInt();
int result = MyLibrary.TriplePlusThree(num);
System.out.println("3x + 3 = "+result);
String letters = "ABCDEFGHIJ";
MyLibrary.MyRecord[] TenRecs = new MyLibrary.MyRecord[10];
for (int i = 0; i < 10; i++) {
TenRecs[i].number = i; //NullPointerException here
TenRecs[i].letter = letters.charAt(i);
}
}
}
I had no problem getting the method to work just fine; now my goal is to create an array where each member of the array has an integer and character. (Note: I'm not looking for better ways to accomplish this objective; I'm merely using this trivial example to try to get this working).
When I tried to run my program, I got:
java.lang.NullPointerException
I researched this, and found this page, which says:
If we try to access the objects even before creating them, run time errors would occur. For instance, the following statement throws a NullPointerException during runtime which indicates that [this array] isn't yet pointing to [an] object. The objects have to be instantiated using the constructor of the class and their references should be assigned to the array elements in the following way.
studentArray[0] = new Student();
So, I tried to do that in my Main Program:
MyRecordArray[0] = new MyLibrary.MyRecord();
but that gives this error:
an enclosing instance that contains MyLibrary.MyRecord is required
That error message led me to this Stack Exchange question, which says:
you have to create an object of X class (outer class) and then use objX.new InnerClass() syntax to create an object of Y class.
X x = new X();
X.Y y = x.new Y();
So, in accordance with that answer, I've added these two lines to my program:
MyLibrary mylibrary = new MyLibrary();
MyLibrary.MyRecord myrecord = mylibrary.new MyRecord();
Those lines don't give any warnings or compilation errors, so I feel like I'm one step closer, but I'm still trying to figure out how to make an array. I know if I wanted to make an array of integers, I would simply do this:
int[] TenInts = new int[10];
So, I've tried things like:
myrecord[] TenRecs = new myrecord[10];
MyRecord[] TenRecs = new MyRecord[10];
But nothing is working, and I feel like I'm grasping at straws now. I get the feeling that the right set of eyes could solve this pretty quickly.
You need to declare the inner class as static.
You can modify the code as follows to suit your requirements:
This is the code for MyLibrary
public class MyLibrary {
public static class MyRecord{
int number;
char letter;
public MyRecord(){
number = 0;
letter = '\0';
}
public MyRecord(int number, char letter){
this.number = number;
this.letter = letter;
}
}
public static int TriplePlusThree(int input_number){
return (input_number * 3 + 3);
}
}
This is the code for the MyMainProgram
import java.util.Scanner;
public class MyMainProgram {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
System.out.println("Enter number to process");
int num = in.nextInt();
System.out.println("3x + 3 = " + MyLibrary.TriplePlusThree(num));
String letters = "ABCDEFGHIJ";
MyLibrary.MyRecord[] TenRecords = new MyLibrary.MyRecord[2];
for (int i=0; i<TenRecords.length; i++){
TenRecords[i] = new MyLibrary.MyRecord();
TenRecords[i].number = i;
TenRecords[i].letter = letters.charAt(i);
}
// Printing class records
for (int i=0; i<TenRecords.length; i++){
System.out.println("Printing records of record " + i + " : ");
System.out.println("Number : " + TenRecords[i].number);
System.out.println("Letter : " + TenRecords[i].letter);
}
in.close();
}
}
You can create the instance of the inner class as follows:
TenRecords[i] = new MyLibrary.MyRecord();
Hope this helps.
The nested class MyRecord contains a hidden reference to the outer class MyLibrary and therefore must be associated with an instance of MyLibrary. This way MyRecord can access private members of MyLibrary.
MyLibrary.MyRecord myrecord = mylibrary.new MyRecord();
Wow, this is funny syntax. In all my years of java programming, I never used such a construct. Typically, you would create objects of inner classes (MyRecord) within the outer class (MyLibrary). Another common thing is to declare the inner class as static which would eliminate the need for an instance of the outer class.
MyRecord[] TenRecs = new MyRecord[10];
This will create an array where all the elements are NULL. You have to initialize each of them (e.g. with a loop).
If you initialize MyRecord[10] the array has null objects. You still have to initialize each element in the array to a new MyRecord object. Otherwise you will get the NPE.
one way to do is : List<MyRecord> TenRecs = new ArrayList<MyRecord>();
TenRecs.add( new MyRecord() );
or for ( int i = 0; i < 10; i++ ) TenRecs[i] = new MyRecord();
also if you add an import statement : import mymainpackage.MyLibrary.MyRecord; You don't need to do mylibrary.new MyRecord(); just do new MyRecord();
You have to create each object in array before initialize. Refer to this link.
Create each object like this.
MyLibrary outer = new MyLibrary();
TenRecs[i] = outer.new MyRecord();
Full code:
MyLibrary.MyRecord[] TenRecs = new MyLibrary.MyRecord[10];
for (int i = 0; i < 10; i++) {
MyLibrary outer = new MyLibrary();
TenRecs[i] = outer.new MyRecord();
TenRecs[i].number = i;
TenRecs[i].letter = letters.charAt(i);
}
There are several points you need to note.
First, difference between a instance inner class and a static inner class.
An instance inner class, declared without static modifier,
public class OutterClass {
public class InstanceInnerClass {}
}
should be created like this:
OutterClass outter = new OutterClass();
InstanceInnerClass iInner = outter.new InstanceInnerClass();
while a static inner class, declared with static modifier,
public class OutterClass {
public static class StaticInnerClass {}
}
should be created like this:
StaticInnerClass sInner = new OutterClass.StaticInnerClass();
Secondly, you accessed an array entry before it is filled
MyLibrary library = new MyLibrary();
MyLibrary.MyRecord[] TenRecs = new MyLibrary.MyRecord[10];
for (int i = 0; i < 10; i++) {
// Create new instance
TenRecs[i] = library.new MyRecord();
TenRecs[i].number = i;
TenRecs[i].letter = letters.charAt(i);
}
So, I'm trying to practice my java skills by applying it to some math homework and making a frequency distribution chart using inheritance. In my head, I envision it as a frequency distribution (parent class = FreqDist) that can have multiple "MyStatClasses" (in the form of the MyStatClass array). Each FreqDist has variables that span across all MyStatClasses which is why I put them in the parent class. However, when I call the MyStatClass constructor, my program gets a StackOverflowError. I think this is because the super(s, i) line calls back to the FreqDist constructor and starts over, causing an infinite loop. Assuming this is the case, how would I fix this?
Ideally, I'd like to access my MyStatClass array and grab values that only apply to that MyStatClass, but I cannot get it to work.
public class FreqDist {
private MyStatClass[] freqClasses;
private double[] dblValuesArray;
private int intNumberOfClasses;
private double dblMax;
private double dblMin;
private int intClassWidth;
public FreqDist(String strValues, int intNumOfClasses) {
System.out.println("This is the beginning of the FreqDist constructor...");
dblValuesArray = getDoubleValues(strValues);
intNumberOfClasses = intNumOfClasses;
dblMin = dblValuesArray[0];
dblMax = dblValuesArray[dblValuesArray.length - 1];
intClassWidth = (int)Math.ceil((dblMax - dblMin) / intNumberOfClasses);
freqClasses = new MyStatClass[intNumberOfClasses];
for (int x = 0; x < freqClasses.length; x++) {
freqClasses[x] = new MyStatClass(strValues, intNumOfClasses);
}
}
public double[] getDoubleValues(String strValues) {
String[] strValuesArray = strValues.trim().split(" ");
dblValuesArray = new double[strValuesArray.length];
for (int x = 0; x < strValuesArray.length; x++) {
dblValuesArray[x] = Double.parseDouble(strValuesArray[x]);
}
Arrays.sort(dblValuesArray);
return dblValuesArray;
}
public int getNumberOfClasses() {
return intNumberOfClasses;
}
public double getMin() {
return dblMin;
}
public double getMax() {
return dblMax;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("What are the values? ");
String values = scan.nextLine();
System.out.print("How many classes? ");
int classes = scan.nextInt();
FreqDist fd = new FreqDist(values, classes);
}
}
public class MyStatClass extends FreqDist {
public MyStatClass(String s, int i) {
super(s, i);
}
}
Ok so this is mostly an issue with a flaw in your design.
From what I understand FreqDist is a class that should contain an array of MyStatClass. You want them to have the same properties so you make MyStatClass extend FreqDist. However when you call FreqDist it MyStatClass which Calls a new MyStatClass over and over and over.
One way to solve this is to create a new class that has the shared properties you want FreqDist and MyStatClass to have, and have those two classes inherit from said class. Then create separate constructors for FreqDist and MyStatClass.
A parent type should never refer to its own subtypes, as yours does. Her the parent initializes subtype instances, which require that each initialize the parent type, which initializes subtype instances, which initialize their parent type, which initializes... KABLOOEY!
I'm trying to create a method which will create an object which contains a 2D boolean array, with int parameters as the number of rows and columns. Then inside the class, I have methods that try to grab the length and width of that array. The two ways I tried to solve this problem were:
public GameOfLife(int rows, int cols) {
boolean[][] society = new boolean[rows][cols];
}
public int numberOfRows() {
return society.length;
}
In my tests, this attempt was giving me the error that society cannot be resolved to a variable. Then I tried:
private boolean[][] society;
public GameOfLife(int rows, int cols) {
boolean[][] temp = new boolean[rows][cols];
society = temp;
}
EDIT: Oops, forgot to add my method for numberOfColumns:
public int numberOfColumns() {
return cols;
}
But the issue with this one was that it was returning 0 instead of 4 when I tried:
#Test
public void FailedTestingRowsAndCols(){
GameOfLife g1 = new GameOfLife(4,4);
assertEquals(4, g1.numberOfColumns());
}
I'm rather new to this, so I apologize if this is a dumb question, but I'm not really sure about all the details of where and when variables expire, which is giving me a lot of difficulties. THank you for any help!
When I create a 2D array outside of my constructor, I'm not able to resize it, but when I create one inside of it, I'm not able to access it
Take note that you will never be able to resize an array. An array once created has its size fixed. You are merely assigning your current array to reference to another newly created array (which gives you the illusion that you successfully resized it).
As for your question of not being able to access it is highly likely the variable you created exist within different scope.
You can use the following codes (which is very similar to yours), it works fine for me. Hence I am guessing your error does not actually comes from the code snippet you showed.
class TestRunner
{
public static void main(String[] args){
GameOfLife gol = new GameOfLife(5, 3);
System.out.println(gol.getColumns());
System.out.println(gol.getRows());
}
}
class GameOfLife
{
private boolean[][] society;
public GameOfLife(int rows, int cols){
society = new boolean[rows][cols];
}
public int getColumns(){
return society[0].length;
}
public int getRows(){
return society.length;
}
}
Output:
5
3
I don't see any problems with what you have posted so far. The below example works fine for me:
public class GameOfLife {
public static void main(String[] args) {
GameOfLife g1 = new GameOfLife(4,4);
System.out.println(g1);
}
private boolean[][] society;
#Override
public String toString() {
final StringBuffer sb = new StringBuffer("GameOfLife{");
sb.append("society=").append(society == null ? "null" : Arrays.deepToString(society));
sb.append('}');
return sb.toString();
}
public GameOfLife(int rows, int cols) {
boolean[][] temp = new boolean[rows][cols];
society = temp;
}
}
If I have an array that gets updated as I run a program (say I ask the player for 5 numbers), call is ClassA and then want to save it using a different class, call it ClassB that imports the data from ClassA, how would I do this?
I am able to create a global variable and pass that information to ClassB but how would I pass a method that takes an argument from a different method to this file?
Here is what I have attempted so far:
class quiz
{
--- other code irrelavent to question ---
public static int[] scorearrayp1()
{
int[] scorep1 = new int[4]; // this creates the array that gets filled later
return new int[4];
}
public static void askQ(scorep1)
{
JOptionPane.showInputDialog("Some numbers");
// this method then fills the array depending on user input
// it is the values from here that I wish to save in classB
}
public static int[] passArray(int[] scorep1)
{
return scorep1; // this is from class A and takes the value from a method before
}
And this is the class I want to send this array to:
class saveScores
{
public static void main(String[] params) throws IOException
{
PrintWriter outputStream = new PrintWriter(new FileWriter("scores.txt"));
finalproject data = new finalproject();
int[] scores = data.passArray(int[] scorep1);
for (int i = 0; i < scores.length; i++)
{
outputStream.println(scores[i]);
}
outputStream.close();
System.exit(0);
}
}
At the moment I'm being thrown two errors
error:'.class' expected
int[] scores = data.passArray(int[] scorep1);
^
error:';' expected
int[] scores = data.passArray(int[] scorep1);
^
I had the idea to change passArray(int[] scorep1) to passArray(scorep1) but then it just tells me that the symbol cannot be found.
Change
int[] scores = data.passArray(int[] scorep1);
to
int[] scores = data.passArray(scorep1);
But still you will need to declare scorep1, for example like:
int[] scorep1 = new int[]{1, 0, 0}
According to your edited question (and if I understand right), your code should look like the following:
int[] scores = quiz.passArray(quiz.scorearrayp1());
Anyway, please keep in mind that class names should always be uppercase.
You can do something like this:
class quiz{
int[] scorep1 = null;
public quiz()
{
scorep1 = new int[4]; // this creates the array that gets filled later
}
public static int[] askQ()
{
JOptionPane.showInputDialog("Some numbers");
// here call fills the array depending on user input
}
And do this:
int[] somearray = quiz.askQ();
int[] scores = data.passArray(somearray);
You should create an array somearray like above to pass at the method data.passArray(somearray);
Whenever I try to test my code with JUnit, I receive a NullPointerException - even though I don't get that exception when I run the actual program. The line that gives me the exception is:
assertEquals(0.0, TweetClassification.tweetType[TweetClassification.SIGNIF_OTHER].likelihoodA);
The beginning of the TweetClassification class it's testing is as follows:
public class TweetClassification
{
// CONSTANTS =============================================
public static final int TCNUMBER = 5; // number of TweetCategories (including the null category)
// using constants to indicate the names of the TweetCategories, so that they could be renumbered
public static final int NULLTWEET = 0;
public static final int SIGNIF_OTHER = 1;
public static final int FRIENDS = 2;
public static final int WORK = 3;
public static final int FOOD = 4;
public static final TweetCategory[] tweetType = new TweetCategory[TCNUMBER];
...
(TweetCategory is another class that is defined separately within the package.) So I realize that this code initializes the array but not its members, and that's probably why I'm getting the exception(?) But the thing is, I do initialize the members of the array within the main method of TweetClassification, as follows:
for (int i=0; i<TCNUMBER; i++)
{
tweetType[i] = new TweetCategory();
}
But if I try to move this for loop outside the main method with the constants I get a syntax error - I presume you're not supposed to use a for loop outside of a method. So I'm not sure how to initialize the class properly for JUnit to work - either I do it outside the main method and get a syntax error, or I do it inside the main method and get a NullPointerException. Any ideas?
You need to move the init code into a static initializer block, like this:
public class TweetClassification
{
//...
public static final TweetCategory[] tweetType = new TweetCategory[TCNUMBER];
static
{
for (int i=0; i<TCNUMBER; i++)
{
tweetType[i] = new TweetCategory();
}
}
//...
}
This ensures that the static variable is initialized properly when the class is loaded (i.e. before it is first used anywhere within your program or tests).
Yo might find some use of the static initialzier block:
private static Integer arr[] = new Integer[2];
static {
for (int i = 0; i < 2; i++) {
arr[i] = 2;
}
}
public static void main(String[] args) {
System.out.println(arr[1]);
}
Ouputs:
2
This is proper java and is meant exactly for initializing static variables, though it is not very commonly used.