Java, Array of Objects - java

This is a trivial question, but my Java is rusty and it's got me stumped; I am getting a null-pointer exception. It may be obvious what I am trying to do based on the code below - but I will explain...
I need an array of objects and I don't want to create another file. For this trivial project, I do not want getters and setters. I have seen an example similar to below that uses a linked list based on a class that is located inside of another class. But, I am more proficient with arrays than linked lists, so I want to use arrays.
public class Ztest {
Stuff[] st = new Stuff[2];
public Ztest(){
}
class Stuff{
public String x;
public boolean y;
public Stuff(){}
}
public static void main(String args[]){
Ztest test = new Ztest();
test.st[0].x = "hello";
test.st[0].y = true;
test.st[1].x = "world";
test.st[1].y = false;
System.out.println(test.st[0].x);
System.out.println(test.st[0].y);
System.out.println(test.st[1].x);
System.out.println(test.st[1].y);
}
}

You need to assign a value to st[0] and st[1] first:
test.st[0] = new Stuff();
test.st[1] = new Stuff();

Java allocates null for object values in new arrays. You'll need something like test.st[0] = new Stuff() before using it.

You need test.st[0]=new Stuff(); etc. since Stuff[] st = new Stuff[2]; creates an array but the elements (references) are still null.
In terms of C/C++ this would be Stuff** st = new Stuff*[2];, i.e. the st is an array of pointers to Stuff instances, whereas the pointers still point to nothing yet.

You need to put an instance of Stuff into test.st[0] and test.st[1].

You can try this if you want to use a list.
static class Stuff {
public String x;
public boolean y;
// generated by my IDE.
Stuff(String x, boolean y) {
this.x = x;
this.y = y;
}
// generated by my IDE.
public String toString() {
return "Stuff{" + "x='" + x + '\'' + ", y=" + y + '}';
}
}
public static void main(String args[]) {
List<Stuff> list = new ArrayList<Stuff>();
list.add(new Stuff("hello", true));
list.add(new Stuff("world", false));
System.out.println(list);
}
prints
[Stuff{x='hello', y=true}, Stuff{x='world', y=false}]

Related

Java ArrayList independent copy

I used the method below to make a copy of a list, as you can see the output, they are independent. Did I get something wrong? or are they really independent? because I did some research on the internet, and it told me this method should pass-by-reference (which list 'a' and 'copy' should be dependent).
public static void main(String[] args) {
ArrayList<String> a = new ArrayList<>(Arrays.asList("X", "X"));
ArrayList<String> copy = new ArrayList<>(a);
copy.set(0, "B");
copy.remove(copy.size()-1);
System.out.println(a);
System.out.println(copy);
}
Output:
[X, X]
[B]
As per the documentation, the ArrayList copy constructor:
Constructs a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.
Modifying one list has no effect on the other, which your code confirms.
Yes, this method should pass-by-reference (which list 'a' and 'copy' should be dependent). But these two operations don't prove this.
copy.set(0, "B");
copy.remove(copy.size()-1);
See if the following code helps you understand:
public static void main(String[] args) {
Process process = new Process(1);
Process process2 = new Process(2);
ArrayList<Process> a = new ArrayList<>(Arrays.asList(process, process2));
ArrayList<Process> copy = new ArrayList<>(a);
copy.get(0).id = 10;
// This proves that both ArrayLists maintain the same Process object at this point
// output:
// [Id:10, Id:2]
// [Id:10, Id:2]
System.out.println(a);
System.out.println(copy);
// copy.remove(copy.size() - 1) or copy.set(0, process3) doesn't affect another ArrayList
Process process3 = new Process(3);
process3.id = 100;
copy.set(0, process3);
copy.remove(copy.size() - 1);
// output:
// [Id:10, Id:2]
// [Id:100]
System.out.println(a);
System.out.println(copy);
}
static class Process {
public int id;
public Process(int id) {
this.id = id;
}
#Override
public String toString() {
return "Id:" + id;
}
}

Linking java functions/subroutines

I am developing a slots machine game as part of an assignment.
I have two functions that I need to link together, shown below:
public static void DisplayOnScreen(){
int LeftVal = GenerateNumber();
int MidVal = GenerateNumber();
int RightVal = GenerateNumber();
FruitVal1 = showFruit[LeftVal];
FruitVal2 = showFruit[MidVal];
FruitVal3 = showFruit[RightVal];
System.out.println(" |",FruitVal1, "|", FruitVal2, "|", FruitVal3, "| ");
--
public String showFruit(int inVal) {
String[] strFruitArr = new String[6];
strFruitArr[0] = "Orange";
strFruitArr[1] = "Pear";
strFruitArr[2] = "Banana";
strFruitArr[3] = "Cherry";
strFruitArr[4] = "Lemon";
strFruitArr[5] = "Apple";
strFruitArr[6] = "Bar";
while(inVal > 0){
if(inVal == 0){
return strFruitArr[0];
}
else if (inVal == 7){
return strFruitArr[6];
}
else{
return strFruitArr[inVal];
}
}
}
As you can see, each "FruitVal" is assigned by taking for example "LeftVal" which is a randomly generated number, and applying that to one of the fruits from the "showFruit" function. I'm aware this is done completely wrong however i do not understand the different java functions to do so.
Could someone explain the basic java functions e.g. 'public static void' and try and help implement them in to this code correctly.
If anyone wants to see the full program code then please do ask, I wasn't sure if the full code was necessary, however it is only short.
Learn Java coding standards. Your code will be more readable.
You link them by having one method return the data that the other needs to have passed to it.
public void displayFruitOnScreen(String [] fruit) {
// display here
}
public String [] getFruit() {
// populate the fruit array here
}
Neither of these is static; they are associated with some instance of a Java class.

Abstract class cannot be instantiated

I had to create this point program a year ago, a year ago it worked fine. Now I have to revisit it and upon compiling and trying to run it I ran into the error of the fact that an abstract class cannot be instantiated. I have done some looking around online and figured out that some update or sort with Java has made it where the method of using PointClass point1 = new PointClass(); is no longer valid and will through an error.
I have yet to find an answer for fixing the error when trying to instantiate the class using a driver program. I also saw that in order to use an abstract class now, a subclass must be present. The thing is is that due to the instructions of the program I cannot use a subclass. Only the driver and the point class.
The program is very simple, just declare some points and call them from the abstract class in order to print to the screen. I need some help on figuring out the updated method to make this work again without the instantiated error.
The PointClass
public abstract class PointClass {
private int pointX;
private int pointY;
//set instance variables
public PointClass() { this.pointX = 10; this.pointY = 10; }
public PointClass(int x, int y){ this.pointX = x; this.pointY = y; }
//make getters and setters
public void setPointX(int x) { this.pointX = x; }
public void setPointY(int y) { this.pointY = y; }
public int getPointX() { return this.pointX; }
public int getPointY() { return this.pointY; }
//make string for format with driver
public String toString() { return "x = " + this.pointX + " y = " + this.pointY; }
}
The Driver
public class PointTest {
public static void main(String[] args){
System.out.println();
PointClass point1 = new PointClass(); //set point1 as no argument
PointClass point2 = new PointClass(11, 24); // set point2 as argument with x and y
System.out.println("Point1: " + point1); //display point1 from toString method
System.out.println();
System.out.println("Point2: " + point2); //display point2 from toString method
System.out.println("---------------------");
}
}
The best thing to do would be to remove the abstract keyword. There's no need for it. Point has no abstract methods.
If you can't do that for whatever reason, you can create inline anonymous classes by adding curly braces after each instantiation:
PointClass point1 = new PointClass() { };
PointClass point2 = new PointClass(11, 24) { };
By the way, your claim that this used to work is incorrect. It has never been possible to directly instantiate an abstract class. That is in fact the entire point of the keyword, to prevent a class from being instantiated.

Object Oriented Programming - Avoid Switch/Case and If/else (JAVA)

I got a problem where I am not allowed to use switch/case or if/else queries.
I got a config file I read which is this:
650;0;1.5;month
614;0;2.88;year
466;0;2.48;week
716;0;4.6;half-year
718;0;2.6;quarter
I am splitting those Strings at the ";", so it is saved in an array. The problem I have, that I need to do other things in the code for each time given in that array ar[3], so if it is a month I need other calculations then when it is a full year.
But I am not allowed to do this with Switch/case or If/Else, now I am getting confused.
If (ar[3] = month){
do this;
else if (ar[3] = year) {
do this;
}
How am I doing this object oriented? Thanks for every help :)
Polymorphism by Inheritance is your friend
It seems like you need some sort of inheritance structure based on the time period in ar[3]. The special do this method could be coded for each case. That way you get the ability to do something different for each case. You just need a way to instantiate the correct subtype in the first place. There are a number of ways you could approach this.
The Conditional Operator
The most direct approach IMHO is the conditional operator, ?:.
So the code would look something like this:
MyClass x = ar[3].equals("month") ? new MyClassMonth() :
(ar[3].equals("year") ? new MyClassYear() :
(ar[3].equals("week") ? new MyClassWeek() :
(ar[3].equals("half-year") ? new MyClassHalfyear() :
new MyClassQuarter())));
x.doSomething();
The nested conditional expressions give you the ability to select the right class, and the inheritance gives you the polymorphic behavior you want.
But you mentioned in comment that you also can't use ?:. What next?
A Map of Stateless Objects
Suppose you wrote MyClassMonth in a way that nothing in it depended on any remembered state, i.e. the doSomething() method has no side effects. Then you could create a Map<String, MyClass> to store one instance of each subclass, then pull the relevant one out of the map when you needed to invoke.
You'd initialize the map like this:
final Map<String, MyClass> themap = new HashMap<>();
{
themap.add("month", new MyClassMonth());
themap.add("year", new MyClassYear());
themap.add("week", new MyClassWeek());
themap.add("half-year", new MyClassHalfyear());
themap.add("quarter", new MyClassQuarter());
}
And invoke doSomething() with ar as argument:
MyClass x = themap.get(ar[3]);
if (x != null)
x.doSomething(ar);
Other Options
There are other ways to do this. Sticking with the Map concept, you could store class literals in the Map instead of instances, then instantiate them reflectively. You could also keep a lambda in the Map and invoke it.
Enums
#OldCurmudgeon suggested using enums. If you put those enums into the Map and add a lambda to the enum, you can grab the enum and invoke the lambda. That would work and has a certain appeal, but it seems unnecessary. You'd be better off just invoking the lambda directly.
You could use an enum as a command factory pattern and implement the choice with a Map lookup.
// Lookups for teh period.
static final Map<String, Period> lookup = new HashMap<>();
enum Period {
Month("month") {
#Override
void process(int x, int y, double v) {
// Processing for "month" records here.
System.out.println(this + "-process(" + x + "," + y + "," + v + ")");
}
},
Year("year") {
#Override
void process(int x, int y, double v) {
// Processing for "year" records here.
System.out.println(this + "-process(" + x + "," + y + "," + v + ")");
}
},
Quarter("quarter") {
#Override
void process(int x, int y, double v) {
// Processing for "quarter" records here.
System.out.println(this + "-process(" + x + "," + y + "," + v + ")");
}
},
HalfYear("half-year") {
#Override
void process(int x, int y, double v) {
// Processing for "half-year" records here.
System.out.println(this + "-process(" + x + "," + y + "," + v + ")");
}
};
Period(String inData) {
// Record me in the map.
lookup.put(inData, this);
}
abstract void process(int x, int y, double v);
static void process(String data) {
String[] parts = data.split(";");
Period p = lookup.get(parts[3]);
if (p != null) {
p.process(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Double.parseDouble(parts[2]));
}
}
}
public void test() {
String[] test = {"650;0;1.5;month",
"614;0;2.88;year",
"466;0;2.48;week",
"716;0;4.6;half-year",
"718;0;2.6;quarter",};
for (String s : test) {
Period.process(s);
}
}
correctly prints:
Month-process(650,0,1.5)
Year-process(614,0,2.88)
HalfYear-process(716,0,4.6)
Quarter-process(718,0,2.6)
Note that there is one if in there but that is only defensive to avoid bad data - it is not part of the lookup mechanism.
Something like this:
public interface Calculator {
double calculate(int p1, int p2, double p3);
}
public class YearCalculator implements Calculator {
public double calculate(int p1, int p2, double p3) {
double value = 0.0;
// do year calculations
return value;
}
}
public class CalculatorFactory {
public Calculator getInstance(String type) {
Calculator calculator = null;
if (type != null) {
} else {
throw new IllegalArgumentException("calculator type cannot be null");
if ("year".equalsIgnoreCase(type)) {
} else {
System.out.println(String.format("No such type: %s", type));
}
}
return calculator;
}
}
You have to have if/else logic in the factory, but not when you're parsing the text.
Your processing code:
CalculatorFactory factory = new CalculatorFactory();
// contents is a List of Strings from your input file.
for (String line : contents) {
String [] tokens = line.split(";");
Calculator calculator = factory.getInstance(tokens[3]);
double value = calculator.calculate(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1]), Double.parseDouble(tokens[2]));
}
Building upon the suggestion given by Codebender as an alternative solution:
You need 5 classes, one for each case, with a common interface but different implementations.
Your interface may look something like this:
public interface MyCalculator {
public double calculate(double a, double b, double c);
}
Then you will need to implement your 5 classes similar to this. You will need a different class with a different implementation for calculate for month, year, week, half-year and quarter:
public class MyMonthCalculator implements MyCalculator {
#Override
public double calculate(double a, double b, double c) {
// Do your calculations here then return
}
}
Then, before your parsing logic, you can add the five classes to a Map.
map.put("month", new MyMonthCalculator());
// Repeat for year, week, half-year and quarter
To actually perform a calculation:
double result = map.get(ar[3]).calculate(Double.parseDouble(ar[0]), Double.parseDouble(ar[1]), Double.parseDouble(ar[2]));
You can simulate if or case with arrays of options. Only problem here would be finding index of our element in such array. We can't use if and case but I assume that while is an option.
So your code can be similar to something like:
String[] options = { "foo", "bar", "baz" };
Runnable[] action = { new Runnable() {
#Override
public void run() {
System.out.println("handling foo");
}
}, new Runnable() {
#Override
public void run() {
System.out.println("handling bar");
}
}, new Runnable() {
#Override
public void run() {
System.out.println("handling baz");
}
} };
String choice = "bar";
int matched = 0;
int i = -1;
while (matched != 1) {
i++;
matched = boolToInt(options[i].equals(choice));
}
action[i].run();
I used method like this to convert boolean to integer where 1=true, 0=false
public static int boolToInt(Boolean b) {
return 5 - b.toString().length();
}
Instead Runnable you can provide your own interface.

Interesting issue about java and linking "&"

I know that there isn't way to access to the links of variables in java (like in &C or &php). But for example I have such task:
public class JustTest {
private int n = 1;
private int x = 10;
public int[] getIntegers() {
return new int[] { n, x };
}
public void filledInteger() {
int[] vals = getIntegers();
System.out.println("Before change");
System.out.println(Arrays.toString(vals));
vals[0] = 2;
vals[1] = 20;
System.out.println("After change");
System.out.println(Arrays.toString(vals));
System.out.println("Values of name & xml");
System.out.println(n);
System.out.println(x);
System.out.println("calling getIntegers");
System.out.println(Arrays.toString(getIntegers()));
}
public static void main(String[] args) {
JustTest t = new JustTest();
t.filledInteger();
}
}
The result is:
Before change
[1, 10]
After change
[2, 20]
Values of name & xml
1
10
calling getIntegers
[1, 10]
So, I want to change values of "n" and "x" fields of the class instance. I can't do this by setting straightly (this->n = 20;), because I may dont know what fields do I have. Only method getIntegers knows.
(No in this code, but for example I have child class with its own fields and in the parent class I have a method filledInteger() which should change specified properties of the child class ( he knows about this properties from the method getIntegers which is abstract in the parent class and implemented in the child class))
Here is simple implementation (without inheritance), using links in php
<?php
class JustTest {
private $n = 1;
private $x = 10;
public function getIntegers() {
return array( &$this->n, &$this->x );
}
public function filledInteger() {
$vals = $this->getIntegers();
echo("Before change" . "<br/>");
echo(print_r($vals, true) . "<br/>");
$vals[0] = 2;
$vals[1] = 20;
echo("After change" . "<br/>");
echo(print_r($vals, true) . "<br/>");
echo("Values of n & x". "<br/>");
echo $this->n , "<br/>";
echo $this->x , "<br/>";
echo("call getIntegers again" . "<br/>");
echo(print_r($this->getIntegers(), true) . "<br/>");
}
}
$t = new JustTest();
$t->filledInteger();
?>
The result is:
Before change
Array ( [0] => 1 [1] => 10 )
After change
Array ( [0] => 2 [1] => 20 )
Values of n & x
2
20
call getIntegers again
Array ( [0] => 2 [1] => 20 )
That is what I exactly need. Im just curious how do I implement this in java
Hope you understood.
Next example:
public abstract class ParentTest {
abstract int[] getIntegers();
public void fillIntegers(int[] newIntegers) {
int[] integersOfChild = getIntegers();
for (int i = 0; i < integersOfChild.length; i++) {
integersOfChild[i] = newIntegers[i];
}
}
}
public class ChildTest extends ParentTest {
private int x;
private int y;
#Override
int[] getIntegers() {
return new int[] {x, y};
}
}
public class UseTest {
void main() {
List<ParentTest> list;
for (ParentTest item : list) {
item.fillIntegers(myItegers);
}
}
}
This is what I need. I have a list of ParentTest instances (it may be ChildTest, or ChildTest2, or ChildTest3; but they all children of a ParentTest) and I need to fill all fields with my integer values, but I dont know if items in the list instances of a ChildTest, or ChildTest2, or ChildTest3 class
How do I implement this in Java?
With great pain via the Reflection API. If you want to write code like this, the best idea is to use another language.
Consider programming in Groovy instead. You can use array syntax to directly access class members by name: t["n"] = 2; This works with legacy Java code, so there is no need to modify TestClass to support this usage.
The concept you are talking about is called pass by reference. Java has for the most part abandoned it - it creates too many side-effects, like the one you are seeing here.
The issue is that while unfortunately you can't do this here, it actually prevents a huge number of unintentional bugs being released.
What about something like that:
public final class JustTest {
private final Map<String, Object> fields;
public void filledInteger() {
System.out.println("Before change\n" + this.fields);
fields.put("N", 2);
fields.put("X", 20);
System.out.println("After change\n" + this.fields);
System.out.println("Values of name & xml\n" + fields.get("N")
+ "\n" + fields.get("X"));
}
private JustTest() {
this.fields = Maps.newHashMap(); // guava
fields.put("N", 1);
fields.put("X", 10);
}
public static void main(String[] args) {
final JustTest t = new JustTest();
t.filledInteger();
}
}
You can't do individual fields without reflection, but you can change the contents of collections. Note that this is not really intended behavior, but rather something you have to be careful of when using collections.
This outputs 5 3 2 4 2 4
public class Test
{
public Vector<Integer> args = new Vector<Integer>();
public void fillArgs()
{
args.add(5);
args.add(3);
}
public Vector<Integer> getArgs()
{
return args;
}
public static void main(String args[])
{
Test s = new Test();
s.fillArgs();
Vector<Integer> temp = s.getArgs();
for (Integer i : temp)
System.out.println(i);
temp.setElementAt(2, 0);
temp.setElementAt(4, 1);
for (Integer i : temp)
System.out.println(i);
for (Integer i : s.getArgs())
System.out.println(i);
}
}
Your php example does not return an array of ints, but rather an array of int pointers. This is NOT something you can do in Java, in fact, this is NOT something you want to do in Java. Give a use case, and there is likely a better way to solve the problem you have.
If you want to return an object that others can affect and that are contained as member variables, do that. An ArrayList, HashMap, etc... there are plenty of things that can fit your needs. If you are given someone elses class and you must stick your nose in their code, you can get around their private declaration doing the following:
public void setN(JustTest j, int n) {
//You would handle some exceptions here also
Field f = JustTest.class.getDeclaredField("n");
f.setInt(j, n);
}

Categories