Hope this is not a duplicate because I already looked up some thread incl. this one, but it didn't help me.
My program is reading in some arguments that are optional by the user. They can add a rule to the game but don't have to.
I know that the rule will be containing 5 Numbers. I wanted to save them in a String Array with 5 spots so I can use them later. If the user won't enter a rule there will be a specific rule taken.
String[] rule = new String[5];
//reading in the program arguments and stuff..
//here I want to check whether the rule is taken from the user or not
//don't want to check with a boolean check
if (rule[0].equals("")) {
String[] newRule = "270-90-315-45-90".split("-");
for (int i = 0; i < newRule.length; i++) {
rule[i] = newRule[i];
}
}
Already tried this:
rule[0].equals("")
rule[0].equals(null)
rule[0].equals("null")
rule[0].matches("")
rule[0].matches("null")
rule.length == 0
rule.equals(null)
But I always get a NullPointerException or the if case will be skipped (length == 0)
Hopeyou can help me.
You didn't have tried the obvious?
if (rule[0] == null) {
Insted of using an fixed array, try using an ArrayList and add the values to the list. The ArrrayList-class will adjust the length of the list automaticly.
Example:
ArrayList<String> rules = new ArrayList<>();
if (rules.size() == 0) {
String[] newRule = "270-90-315-45-90".split("-");
//Instead of newRule.length as a comparison, use the
//number of rules with a number. Or use a foreach-loop
//if the number of rules may vary
for (int i = 0; i < 5; i++) {
rules.add(newRule[i]);
}
}
In the example you provide us with, rule[0] contains the value null which you can see yourself by adding the following line of code:
System.out.println(rule[0]==null);
returns true (try it !)
if (rule[0]==null) {
will return true and get inside the for loop if that is what you want.. See the following class which you can compile (using javac myEmpty.java) and run (using java myEmpty):
class myEmpty {
public static void main(String[] args) {
String[] rule = new String[5];
System.out.println(Arrays.toString(rule));
//reading in the program arguments and stuff..
//here I want to check whether the rule is taken from the user or not
//don't want to check with a boolean check
System.out.println(rule[0] == null);
if (rule[0] == null) {
//if ("".equals(rule[0])) {
String[] newRule = "270-90-315-45-90".split("-");
System.out.println(Arrays.toString(newRule));
for (int i = 0; i < newRule.length; i++) {
rule[i] = newRule[i];
System.out.println(rule[i]);
}
}
}
}
YOUR if if (rule[0].equals("")) { fails simply because rule[0] does not contain the value "" which you are checking for ! Keep in mind that "" and null are not the same, and use your if clauses accordingly !
So you want to change indices entered by user only.
The best way to do this would be to initialize the array with default values, then override those specified by the user.
String[] rule = "270-90-315-45-90".split("-");
// Now read "program arguments and stuff"
The NullPointerException I imagine is coming from the fact you have created an array of strings but have not initialized them with any values. They will default to null if you don't give them a value...hence the NPE.
Depending on where you are getting your input you could do something like this;
private static final String[] DEFAULT_RULES = {"270", "90", "315", "45","90" };
private static String[] rules;
public static void main(String[] args){
if(!isValidRule(args)){
// Potentially also check that the args are digits
throw new IllegalArgumentException("Must contain 5 rules");
}
rules = (args.length > 0) ? args : DEFAULT_RULES; // Used brackets on the ternary operator here for readability. Not essential.
...
}
private static boolean isValidRule(String[] rules){
return rules.length > 0 && rules.length != 5;
}
If you are working with some other non-static method thats taking the input, the same applies. You can perform your string split to get an array based on the delimiter you have specified and then do the same thing.
I don't imagine you would want to be passing around a string containing only hyphens if no rules are passed? Which is what you are hinting at by attempting to check if a string is empty after the split is performed.
Also if you want to check if the string contains characters or not use the isEmpty() method. It returns true if the length is 0 else it returns false. This already achieves what you are needlessly attempting.
In each of your tried options
rule[0].equals("")
rule[0].equals(null)
rule[0].equals("null")
rule[0].matches("")
rule[0].matches("null")
rule.length == 0
rule.equals(null)
You already assumed that your element at 0 index is not null , and calling equals() and matches() method on element at 0th index causing NullPointerException
Thrown when an application attempts to use null in a case where an
object is required. These include:
Calling the instance method of a null object.
Accessing or modifying the field of a null object.
Taking the length of null as if it were an array.
Accessing or modifying the slots of null as if it were an array.
Throwing null as if it were a Throwable value.
Instead try like this
if(rule[0] != null){
// Now you can call methods on your `0th` index element
}
Related
UPDATE: Apologies for the confusion. All code MUST be written between the forward slashes i.e. the "//" beginning at the TO DO comment. And ends the line before the return answer.
Consequently this:
return price<20 ? "Buying new shirt" : null
is unfeasible as return answer is OUTSIDE the allowed code modification area.
I also didn't know if it was possible to assign a null object to a String object (as my comment indicated. And yes, I'm aware of the difference between "null" v null. That is the entire issue I'm having with the code failing to compile.
The ConditionalStatements() method is supposed to pass an integer input and return a string variable called answer.
If the passed integer price < 20 (to include negative integers), then the return variable answer = "Buying new shirt". Otherwise the compiler's expected return value for answer must be null i.e. the OBJECT null and NOT the string "null" which answer is initialized with.
Constraints:
if statement MUST be a Simple Conditional Statement with no branching.
cannot use catch try or other statements. Limited to use of compound conditionals and variables.
MUST be WITHIN the area designated by // forward slashes.
Because of this last constraint, I can't see a way to typecast/return the null as the test errors are indicating. Apologies again for the confusion.
I've tried short circuiting using && and the || operators. Tried getting creative with && and II operators in the if statement to make compound statements. e.g:
if ( (answer.equals(null) && (price >=20) ) etc.
to trap the incorrect test input and change answer data type. But compiler fails test cases of required answer = null for cases where price >= 20. Returning answer = "null" throws an error as a String object is returned v. the desired null.
How to type cast answer variable e.g. (null) answer = null; in my code below?
public class ConditionalStatements {
/**
* This method is used for problem one in the README.
* #param price A price that will be passed in by the test.
* #return String A string used to validate the test.
*/
public String simpleConditional(int price) {
String answer = "null";
**// TODO: Write Step 1 code between the forward slashes** <--start code modification area
(answer == null ) || (price < 20) )
answer = "Buying new shirt";
if( (price >= 20) ) {
answer = null; //this assignment is legal according to post feedback.
//However it STILL results in test failure message (shown in URLs below).
//Where the compiler is expecting a null object and not a string object....
//compiler won't accept answer = null; How to typecast answer String variable so it will accept null object?
}
// **<---this is the END of the code modification area**
return answer;
}
When compiler tries to compile, it fails with these test run errors:
All tests. Only price < 20 passed:
https://i.postimg.cc/TYrH051P/allTests.png
Test 3: price = 20, expected return for answer = null
https://i.postimg.cc/W3GJCVk0/Test3-err1.png
Test 4: price = 21, expected return for answer = null
https://i.postimg.cc/bNJsHk3x/Test4-err2.png
All you have to do assign null to answer variable, rather than "null" string. Check the below code, I think it does what you want to achieve.
public class ConditionalStatements {
/**
* This method is used for problem one in the README.
* #param price A price that will be passed in by the test.
* #return String A string used to validate the test.
*/
public String simpleConditional(int price) {
String answer = null;
// TODO: Write Step 1 code between the forward slashes (answer == null ) || (price < 20) )
if(price < 20){
answer = "Buying new shirt";
}
return answer;
}
public static void main(String[] args){
ConditionalStatements var = new ConditionalStatements();
System.out.println(var.simpleConditional(10)); // prints "Buying new shirt"
System.out.println(var.simpleConditional(25)); // return null object
}
}
To use null with explicit type you have to put a cast in front of null, in you example
if( (price >= 20) ) {
answer = (String) null;
}
I have a ManagementCompany data manager class that stores information about various properties in a Property (a class I defined) type array called properties[]. One of the methods of the class is meant to add properties to that array, and is called addProperty(Property p). It should take the given property and add it to the array in the first available space, if there is any (as seen here:)
Property[] properties = new Property[5];
public int addProperty(Property p) {
if (isArrayFull()) //Method returns true if there is no space, false otherwise
return -1;
else if (p == null) //Make sure p is valid
return -2;
for (int i = 0 ; i < properties.length; i++) { //Loop through all elements in the array
if (properties[i] == null) { //If the space is empty
properties[i] = new Property(p); //Assign a new property to it
return i; //Return the index of the new property
}
}
return -10; //Should never happen, but need it to compile
}
However, when I create and add properties to the array, only the first property is added. After the first property is added, the program doesn't continue adding to the first available space, instead, it seems to just ignore them. It doesn't replace the first one, and doesn't add it to the array (which is initialized to a length of 5). Any suggestions as to why?
Tests I'm running on it:
ManagementCompany mgmCmp = new ManagementCompany();
Property p1 = new Property("Property 1");
mgmCmp.addProperty(p1);
Property p2 = new Property("Property 2");
mgmCmp.addProperty(p2);
System.out.println(mgmCmp.toString());
The result is:
Property 1 null null null null
only the first property is added... Any suggestions as to why?
Because of return i;. You exit the method once you've added one property.
Hope that helps
Found a seemingly unrelated method in another class that was causing the object not to be stored in the array. Thanks for the advice.
Popular problem: print all combinations of input.
Both the first code block and 2nd code block have the same structures. I did debug and track stack, but couldn't understand. That's why I'm posting.
If input is List, the following code works and I understand it.
remain should be backtracked.
ex: input list = ["a", "b", "c"]
public void sublists(List<String> list) {
List<String> chosen = new ArrayList<>();
sublists(chosen, list);
}
private void sublists(List<String> chosen, List<String> remain) {
if(remain.size() == 0) {
System.out.println(chosen);
}
else {
String first = remain.remove(0);
// choose/explore INC. first
chosen.add(first);
sublists(chosen, remain);
// choose/explore EXC first
chosen.remove(chosen.size() -1);
sublists(chosen, remain);
// un-choose for backtracking
remain.add(first);
}
}
However, the same question but different input type, when input is String, doesn't need backtracking of remain in the code below.
Q1: why remain += C; is not reachable in code block below while remain.add(first); is reachable in the code block above even though these two code blocks have the same code structure? In both code block, recursion method get called recursively.
Q2: remain += C; not even needed since it's automatically backed its removed char. Why?
// ex: input s = "abc"
public void combination2(String s) {
combination2Helper("", s);
}
private void combination2Helper(String chosen, String remain) {
if (remain.length() == 0) {
System.out.println(chosen);
}
else {
char C = remain.charAt(0);
chosen += C;
remain = remain.substring(1);
// inc. C + remain w/o C
combination2Helper(chosen, remain);
// exc. C + remain w/o C
chosen = chosen.substring(0, chosen.length() -1 );
combination2Helper(chosen, remain);
// why this backtrack of ramin is not reachable unlike when remain is list
// backtrackig this line is not needed.
remain += C;
}
Besides if the input is string, we don't even need such a long line of code right above.
The following code is working.
Q3: Theoretically we need to backtrack what we've chosen after the recursion call for exhaustive search but why this code doesn't need backtracking of chosen nor remain when the input type is String?
When the input is List, if don't use backtracking, it doesn't work.
I'm confused why the backtracking is not reachable ( not needed ) when input is String while List is needed.
private void combination2Helper(String chosen, String remain) {
if (remain.length() == 0) {
System.out.println(chosen);
}
else {
combination2Helper(chosen, remain.substring(1));
combination2Helper(chosen+remain.charAt(0), remain.substring(1));
}
}
In the list version, you do not need to add C again to the list remain if you copy the list first:
remain = new ArrayList<>(remain);
String first = remain.remove(0);
In the string version, the statement remain += C; will be reached, but it has no real effect, because the value will never be used again. So it can be removed by optimization. The situation is similar to copying the list in the list version. Look at these statements:
char C = remain.charAt(0);
chosen += C;
remain = remain.substring(1);
remain is an argument of the method. This will be assigned with the actual parameter, when the method is called. remain then behaves like a local variable of the method. When a new value is assigned to it inside the method, this will not change the variable passed by the caller (the reference to the string is passed by value).
In my Java program's constructor I have the following:
thirdRow.add(button);
button.setActionCommand("Sumbit");
button.addActionListener(this);
And here is the corresponding actionPerformed method that's supposed to take 3 values from some textfields and store them into arrays:
public void actionPerformed(ActionEvent e)
{
String arg = e.getActionCommand();
if (arg == "Submit")
{
//enlarge arrays
qtyStr = enlargeArray(qtyStr);
typeStr = enlargeArray(typeStr);
colorStr = enlargeArray(colorStr);
//add from textfields into current
qtyStr[qtyStr.length-1] = qty.getText();
typeStr[typeStr.length-1] = type.getText();
colorStr[colorStr.length-1] = color.getText();
}
}
//method to enlarge an array by 1
public String[] enlargeArray(String[] currentArray)
{
String[] newArray = new String[currentArray.length + 1];
for (int i = 0; i<currentArray.length; i++)
newArray[i] = currentArray[i];
return newArray;
}
When I run the application, populate the textfields, and click the submit button nothing happens. How can I verify that my string arrays are being appended like they're supposed to?
You've a problem here: if (arg == "Submit")
Don't compare Strings using ==. Use the equals(...) or the equalsIgnoreCase(...) method instead. Understand that == checks if the two objects are the same which is not what you're interested in. The methods on the other hand check if the two Strings have the same characters in the same order, and that's what matters here. So instead of
if (fu == "bar") {
// do something
}
do,
if ("bar".equals(fu)) {
// do something
}
or,
if ("bar".equalsIgnoreCase(fu)) {
// do something
}
Also, for safety's sake, I try to use String constants wherever possible so as not to be tripped up by misspellings.
If you want to do your code this way, I would probably do two things:
1) maintain index fields for each array for the next free index, and
2) I wouldn't recommend resizing your array by 1 each time, as our current code is running through the array 2 n times (n = array length), 1st to initialize the array, and 2nd to create a new array.
Two options to optimize thisL one would be be to look into the Arrays class. it contains methods such as Array.copyOf() that can perhaps be useful here. You could also check if the array is full, and if it is then resize it by a number greater than one to reduce extra work.
For instance:
import java.util.Arrays;
class Test{
private String[] a;
private int next;
public Test(int size){
a = new String[size];
next = 0;
}
public void add(String s){
if(next == a.length){
Arrays.copyOf(a, a.length+1);
}
a[next] = s;
next++;
}
}
The easiest way would be to use an ArrayList (or any class that implements the java.util.List interface), as previously mentioned by Jon Skeet - it will do all the work for you.
import java.util.Scanner;
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan=new Scanner(System.in);
int i,j;
int count = 0;
int test=scan.nextInt();
String[] con=new String[test];
while(test>0)
{i=scan.nextInt();
j=scan.nextInt();
for(int k=i;k<=j;k++)
if(prime(k))
//***********the line below where i am getting nullpointer exception
con[count].concat(k+"\n");
test--;count++;}
for( i=0;i<con.length;i++)
System.out.printf("%s\n",con[i]);
}
private static boolean prime(int k) {
// TODO Auto-generated method stub
if(k==2)
return true;
if(k%2==0)
return false;
for(int l=3;l<=Math.sqrt(k);l=l+2)
if(k%l==0)
return false;
return true;
}
}
please somebody help me that how to get rid from this exception.
String[] con=new String[test]; creates a new String array with test elements, and assigns it to con. However, this does not create any String objects at all - you have simply created an array where all elements are null. You must ensure that con[count] actually refers to a String before calling concat() on it; you can either do this by checking if it is null and assigning "" to it before calling concat(), or you can have a separate loop that puts an empty string into each element of con.
By the way: concat() does not modify the String you call it on; it creates a new String and returns it, but you don't do anything with the return value, so it gets thrown away. You should use += instead (which also creates a new String, but it will assign the new String to the array element).
You are not initializing each element of con[]
new String[] gives you an array of null string references. You have to set them to the empty string if you want your code to work.
When you do
String[] con=new String[test];
you create a new String-array of length test. The elements in this array, however, start out being null. Therefore, you cannot call concat on them before initializing them to a string.
This means, you should initialize the string to the empty string, "", before doing calling concat on it.
In addition, strings are immutable, so concat produces a new String, rather than modifying the existing one, so you need to save the result.
This means, you all in all want something like:
while(test>0) {
i=scan.nextInt();
j=scan.nextInt();
con[count] = ""; // Initialize con[count]
for(int k=i;k<=j;k++) {
if(prime(k)) {
con[count] = con[count].concat(k+"\n");
}
}
test--;
count++;
}
Since you'r getting NullPointerException here,
con[count].concat(k+"\n");
it means that the value of con[count] is null and you are trying to call .concat( ) on the null instance.
Here, con[] is not initialized, so it takes null by default. You need to initialize the elements of con[] array i.e say to "" and then try calling the concat method.
It looks like conc[count] is null, if that's where you're getting a NullPointerException.
You should initialize it with a value.