Why is global object array suddenly null when it enters a method? - java

Why would a non-null global array suddenly become null in a method?
I have tried to move the method into the object class and access it that way since the getWeight() method works fine, but I have the same issue. As soon as I step into the viablePaths method the global arrays are null. I am using eclipse to toggle breakpoints and I can see everything in the arrays before I step into the method.
I would like the method to be able to access the paths and archs arrays and return an integer value. With the content of the arrays right now the method should set the pathIndex integer variable to -1. I do not know what else to put for the desired behavior. The desired behavior should be for the the global object arrays to not become null when the method is called.
Currently the error I get is a NullPointerException from the line where the determineViable paths method is called.
public class StackHelpProblem {
public static int numEdges;
public static int queries;
public static Edge[] paths;
public static Edge[] archs;
public static void main(String[] args) {
numEdges = 3;
queries = 2;
Edge[] paths = new Edge[numEdges];
paths[0] = new Edge(1);
paths[1] = new Edge(2);
paths[2] = new Edge(3);
Edge[] archs = new Edge[queries];
archs[0] = new Edge(10);
archs[1] = new Edge(10);
int pathIndex = 0;
// Reachable artifacts set
for (int i = 0; i < queries; i++) {
System.out.println(archs[i].getWeight());
pathIndex = determineViablePaths(archs[i].getWeight());
}
}
// Method to return last index of path that can be traversed
public static int determineViablePaths(int weight) {
for (int i = 0; i < numEdges; i++) {
if (paths[i].getWeight() <= weight)
continue;
else {
return i - 1;
}
}
return numEdges-1;
}
// The edge class
public static class Edge implements Comparable<Edge> {
int weight;
Edge(int weight) {
this.weight = weight;
}
public int getWeight() {
return this.weight;
}
// The Edge comparison method
public int compareTo(Edge other) {
if(this.weight < other.weight)
return 0;
else if (this.weight == other.weight)
return 1;
return -1 ;
}
}
}
the getWeight() works and the determineViablePath(int weight) method does not work. As soon as that method is entered the global arrays become null.
Thank you for any assistance.

Let us analyze the relevant parts of the code to understand why the Exception is thrown and how we can prevent it.
public class StackHelpProblem {
...
public static Edge[] paths;
public static Edge[] archs;
...
}
The two static fields Edge[] paths and Edge[] archs are not initialized and thus implicitly initialized with null.
public class StackHelpProblem {
...
public static void main(String[] args) {
...
Edge[] paths = new Edge[numEdges];
...
Edge[] archs = new Edge[queries];
...
}
...
}
In method static void main(...), two new arrays paths and archs are created. Those do not reference the static fields. Thus, the static fields are still initialized with null.
In method static int determineViablePaths(...), no local variable paths is found, thus static field paths is used, which still is null. Thus, the array-access will result in a NullPointerException.
We can get rid of the NullPointerException by using the existing static fields instead of creating new variables in method static void main(...):
public class StackHelpProblem {
...
public static void main(String[] args) {
...
paths = new Edge[numEdges];
...
archs = new Edge[queries];
...
}
...
}
Ideone demo

Related

List add function does not operate properly?

public static void main(String[] args) {
// TODO Auto-generated method stub
List<item> l = new ArrayList<item>();
List<Integer> ll = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
l.add(new item(i,i));
ll.add(i);
}
System.out.println(l.get(4).getWeight());
System.out.println(ll.get(4));
}
public class item {
private static int value;
private static int weight;
public item(int val, int w) {
setValue(val);
setWeight(w);
}
public static int getValue() {
return value;
}
public static void setValue(int value) {
item.value = value;
}
public static int getWeight() {
return weight;
}
public static void setWeight(int weight) {
item.weight = weight;
}
}
This is my code, and then item is class take two paratemers. But when I add the item into list, the elelments in list have same value(in this case it is 9). For Integer, there is no problem. I think I miss some critical parts of java feature.
Any help appreciated, thank you in advance.
All of your methods and members of item are static. That is, they belong to the item class, rather than a specific instance of that class. The static members are shared among every instance of the class, and so every new item you create is using the same set of data. You will want to make them not be static.
Check out the following official tutorials for more info, they are concise and well-written and will help you:
Non-static, member variables: Declaring Member Variables
Non-static, methods: Defining Methods
static class members: Understanding Class Members
Once you have done this, as Takendarkk astutely points out in a comment, be sure to use this.value = ... instead of item.value = ... (no longer valid) or value = ... (uses local scope value instead of member).

copying instances to avoid changing java instance state

Suppose I have a class
public class Test{
Point[] pq = null;
public Test(int Capacity) {
Point[] pq = new Point[Capacity];
}
public static void main(String[] args) {
Point point = new Point(); // suppose it has a given state `state` equal to 0
Test test = new Test(1);
test.pq[0] = point; // here test[0] has a `state` equal to 0
point.state = 1 //Suppose now I change the `state` of the point instance variable to 1
}
...}
public class Point{
public Integer state = 0;
...
}
I changed the state of the point instance variable to 1
then test.pq[0].state is now equal to 1. How can I prevent my code from this behavior ?
Edit 1, in the Point class, I added getter and setters and turned public Integer state into private Integer state = 0, I added this
public void copy(Point point){
this.setState(point.getState())
}
when I call Test test = new Test(1); test.pq[0].copy(point);, I still get te same problem
The clean way to avoid this problem is to make the Point class immutable:
public final class Point
private final int state;
public Point(int state) {
this.state = state;
}
public int getState() {
return state;
}
// no setter !
}
That way, nobody can modify the state of a point, and everything is safe.
If the point needs to be mutable, and you don't want to let callers modify the state of the points of your Test, then you'll have to make copies:
public class Test {
private Point point; // it would be the same with an array or a list
public class Test(Point p) {
// defensive copy
this.point = new Point(p.getState());
}
public Point getPoint() {
// defensive copy
return new Point(p.getState());
}
}
Or course, if your Test has a list or array of points, and if you make the array or list of points accessible from the outside, you can't guarantee anything. That's why every modification should go through a method of the test (that's what encapsulation is all about):
public void addPoint(Point p) {
pointList.add(new Point(p.getState());
}

Superclass resets already active objects

It's a little bit difficult but i'll try to explain my problem. I've created a program with a superclass (RichIndustrialist) two subclasses (PredecessorRichIndustrialist and another one I didn't add) and 4 subclasses to these subclasses (CrazyRichIndustrialist and another 3). Now, the program is too difficult to explain but the problem is actually simple. My constructor is in the superclass and every subclass use it to initilize. Every time I create a new subclass object like CrazyRichIndustrialist, it resets all the already existed subclasses (from any subclass) to the value of the new object. I don't know how to fix this. Thank you in advance...
RichIndustrialist:
package Mortal;
import java.util.Random;
public class RichIndustrialist implements Mortal {
private static String Name;
private static double holdings;
private static int Alive;
public RichIndustrialist(String Rich_Name, double Rich_holdings) {
this.Name = Rich_Name;
this.holdings = Rich_holdings;
this.Alive = 1;
}
public int isAlive() {
return (this.Alive);
}
public void setHoldings(double new_holdings) {
this.holdings = new_holdings;
}
public double getHoldings() {
return (this.holdings);
}
public String getName() {
return (this.Name);
}
public void die() {
this.Alive = 0;
}
public void getHeritage(double heritage) {
this.holdings = this.holdings + heritage;
}
}
PredecessorRichIndustrialist:
package Mortal;
import java.util.Arrays;
public class PredecessorRichIndustrialist extends RichIndustrialist {
private static String Name;
private static double holdings;
private RichIndustrialist[] successors = {};
private static int Alive;
public PredecessorRichIndustrialist(String Rich_Name, double Rich_holdings) {
super(Rich_Name,Rich_holdings);
}
public void die() {
super.die();
}
public void Inheritance(double holdings, RichIndustrialist[] successors) {
int i = 0;
while (i < successors.length) {
int Alive = successors[i].isAlive();
System.out.println(Alive);
if (Alive == 0) {
removeSuccessor(successors[i]);
i++;
} else {
i++;
}
}
}
public void addSuccessor(RichIndustrialist new_successor) {
RichIndustrialist[] new_successors = new RichIndustrialist[successors.length + 1];
if (successors.length == 0) {
new_successors[0] = new_successor;
successors = new_successors;
} else {
for (int i = 0; i < successors.length; i++) {
new_successors[i] = successors[i];
}
new_successors[new_successors.length - 1] = new_successor;
}
this.successors = new_successors;
}
public void removeSuccessor(RichIndustrialist removed_successor) {
RichIndustrialist[] new_successors = new RichIndustrialist[this.successors.length - 1];
int j = 0;
for (int i = 0; i < this.successors.length; i++) {
if (!this.successors[i].equals(removed_successor)) {
new_successors[j] = this.successors[i];
} else {
j--;
}
j++;
}
}
public RichIndustrialist[] getSuccessors() {
return successors;
}
}
CrazyRichIndustrialist:
package Mortal;
import java.util.Random;
public class CrazyRichIndustrialist extends PredecessorRichIndustrialist {
private RichIndustrialist[] successors = {};
private static String Name;
private static double holdings;
private static int Alive;
public CrazyRichIndustrialist(String Rich_Name, double Rich_holdings) {
super(Rich_Name,Rich_holdings);
}
public void die() {
super.die();
Inheritance(getHoldings(),getSuccessors());
}
public void addSuccessor(RichIndustrialist new_successor) {
super.addSuccessor(new_successor);
}
public void removeSuccessor(RichIndustrialist removed_successor) {
super.removeSuccessor(removed_successor);
}
public void Inheritance (double holdings , RichIndustrialist[] successors) {
super.Inheritance(holdings, successors);
for (int i=0; i<successors.length-1; i++)
{
double random = new Random().nextDouble();
double amount = this.holdings * random;
successors[i].getHeritage(amount);
holdings = this.holdings - amount;
}
successors[successors.length-1].getHeritage(this.holdings);
this.holdings = 0;
}
public String getName(){
return super.getName();
}
public double getHoldings(){
return super.getHoldings();
}
public RichIndustrialist[] getSuccessors(){
return super.getSuccessors();
}
public void setHoldings(double new_holdings){
super.setHoldings(new_holdings);
}
public int isAlive() {
return super.isAlive();
}
public void getHeritage(double heritage) {
super.getHeritage(heritage);
}
}
Most of your fields are static. What that means is that all the instances of your classes share the same value. When you call the constructor, the static fields are modified, which affects all the existing instances.
For example:
this.Name = Rich_Name;
should actually have been written:
RichIndustrialist.Name = Rich_Name;
You can read about the difference between instance and class (or static) members in this tutorial.
The following fields should be declared as non-static. When these fields are declared as static each RichIndustrialist instance will share these fields and their assigned values. Declaring them as non-static allows each RichIndustrialist instance to have its own copy of these fields, which is autonomous from the other instances of RichIndustrialist.
private String Name;
private double holdings;
private int Alive;
Here is a good description of static from the Java Tutorial
Sometimes, you want to have variables that are common to all objects.
This is accomplished with the static modifier. Fields that have the
static modifier in their declaration are called static fields or class
variables. They are associated with the class, rather than with any
object. Every instance of the class shares a class variable, which is
in one fixed location in memory. Any object can change the value of a
class variable, but class variables can also be manipulated without
creating an instance of the class.
Your properties/variables are static. and we know static variable are shared between all the objects.
That is the reason the last object will replace the existing value of your variables
Suggestion:
change your static modifier to instance modifier
From
private static String Name;
private static double holdings;
private static int Alive;
To
private String Name;
private double holdings;
private int Alive;
I am sure your problem will resolve.
You are declaring the Name member field in all of your classes, you should only declare it in the super-class and let the other sub-classes (re)use it.
Furthermore, you declared the field as static, all instances of your class will use the same field, which is probably not what you intended, so remove the static part.
Same goes for all of your other member fields.
Note: do not start the member fields with a capital: Name should be defined and used as name. Class names on the other hand should start with a capital! This is a generically accepted Java convention and keeps things more clear/separated.

Passing dynamic primitive type (int) to a method

In Java, the output of s is 0. I do not understand why and would it be possible to somehow get the correct value of s (1000 here)?
public static void main(String args) {
int s = 0;
List<Integer> list = getList(s);
System.out.println("s = " + s);
}
public static List<Integer> getList(int s) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 1000; i++) {
list.add(i); s++;
}
}
In C# there were out descriptors to indicate that the variable is going to change if I'm not mistaken..
I'm not going to get the list.size() in general!
In Java, all method arguments are passed by value, i.e. copy. So, changes to the copy are not visible to the caller.
To address your second question, you can just use list.size() on the caller side.
I see two ways
1) Make 's' as static variable and move it to class level
2) Create class with getter/setter for list and int and return the object for getList call
public static MyWrapperObj getList(int s) {
......
return wrapperObj
}
class MyWrapperObj
{
private List<Integer>;
private countS;
....
//getter/setters.
}
Java doesn't allow for passing parameters by reference - but you could wrap it in an object like this:
class IntHolder {
private int s;
IntHolder(int s){
this.s = s;
}
public void setS(int s){
this.s = s;
}
public int getS(){
return s;
}
public void increment(){
s++;
}
}
class Test{
public static void main(String[] args) {
IntHolder s = new IntHolder(0);
List<Integer> list = getList(s);
System.out.println("s = " + s.getS());
}
public static List<Integer> getList(IntHolder s) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 1000; i++) {
list.add(i); s.increment();
}
return list;
}
}
In java, arguments passed to methods are passed by value.. you will need to make s a global or instance variable in order to modify it in other methods. This is just the way java works. e.g.
public class Test{
private int s;
public Test(){
s=0;
increment();
//print now will be 1000.
}
private void increment(){
s = 1000;
}
}

Java 'this' keyword

I'm just beginning in programming and I'd like to make exercise from a book, but I can't. That's my problem:
public class increment {
int increment() {
return this + 1; // aka this++
}
public static void main(String[] args) {
int a = 0;
System.out.println(a.increment());
}
}
As you for sure guessed already, that it doesn't works, I want to ask you how to get outputed integer a incremented by one, but using keyword 'this'.
Regards and sorry for stupid questions.
It is strange to name a class like a method.
I guess you wanted this:
public class Counter {
int val;
public Counter (int start) {
val = start;
}
public void increment() {
val ++;
}
public String toString () {
return Integer.toString (val);
}
public static void main(String[] args) {
Counter counter = new Counter (0);
counter.increment ();
System.out.println(counter.toString ());
}
}
this is an object (the current object). You cannot "increment" it.
A way to do it is:
public class Increment {
int a = 0;
int increment() {
return a + 1;
// or: return this.a + 1;
// or: a++; return a; if you want a to be incremented from now on
}
public static void main(String[] args) {
Increment inc = new Increment();
System.out.println(inc.increment());
}
}
The this keyword in Java refers to the current scope's object instance. I don't think it's what you're looking for in this case.
In your example, a isn't an object of the class increment, it is a primitive int. In order to use the .increment() function you defined, it would have to be an object of type increment.
One option that may be what you're looking for would be the following.
public class Increment { //Java likes capitalized class names
private int myInt;
public Increment(int a) { //constructor
myInt = a;
}
public int increment() {
return ++myInt;
}
public static void main(String[] args) {
Increment a = new Increment(0);
System.out.println(a.increment());
}
}
In this example, we make a new class of type increment, which internally contains an integer. Its increment method increments that internal integer, and then returns the number.
you are using operator + for your current object (this). Operator overloading is not supported in java.
Something like this will work:
class MyInteger {
private int internal;
public MyInteger( int value ){
this.internal = value;
}
public int incerment(){
return ++this.internal;
}
}
public class Increment {
public static void main(String[] args) {
MyInteger a = new MyInteger(0);
System.out.println(a.increment());
}
}
You see, you can only implement methods for your own classes, not for existing classes, or for primitives like int.
i don't think you can use this to return the value, except if you're making a new class like this:
class Increment1
{
private int a;
public int increment2(int a)
{
this.a=a;
return this.a + 1;
}
}
public class Increment
{
static Increment1 b = new Increment1();
public static void main(String[] args)
{
int a = 0;
System.out.println(b.increment2(a));
}
}
You cannot increment a class like this.
You have to use a member variable that you can increment.
public class Test {
private int var;
public Test(int i) {
this.var = i;
}
int increment() {
this.var++;
}
}
public static void main(String[] args) {
Test t = new Test(0);
System.out.println(t.increment());
}
This refers to the current instance of the class, not a particular member.
You want to increment a property (I'm guessing of type long or int), and not the instance of your increment class (should be Increment, by the way).
Something like this would work:
public class increment {
private int innerValue = 0;
int increment() {
innerValue+=1
return innerValue; // aka this++
}
public static void main(String[] args) {
increment a = new increment()
System.out.println(a.increment());
}
}

Categories

Resources