My java program takes input from the user on the command line. The user has a choice: he may either specify a plain-text file as input with the -inputfile option, or he may leave this option unspecified, in which case the program takes input from System.in. (I've observed this behavior in some programs that come pre-installed with my Ubuntu distro, so I infer that it is acceptable practice.)
So I make a BufferedReader (inBR)that reads from the file, if provided, and a Scanner (inScanner) that reads from System.in otherwise. Only one of these objects is actually instantiated, the other is left as null. Later on, when the program reads a line from input, I have the following code:
String line;
if (inBR != null) {
line = inBR.readLine(); (1)
} else {
line = inScanner.nextLine(); (2)
}
Which gives me the compile time errors variable inBR might not have been initialized and variable inScanner might not have been initialized at lines (1) and (2), respectively.
What is the acceptable solution here? I've considered, "initialize the variable that's supposed to be null as an Object to shut up the compiler." But this is just a hack; surely there's a better way.
Also, why isn't this a runtime exception, as a NullPointerException?
EDIT: inScanner.readLine() => inScanner.nextLine()
Declaring them this way would avoid the compilation error :
BufferedReader inBR = null;
Scanner inScanner = null;
Of course you still have to give them actual values before accessing them, or you'll get NullPointerException.
In java all variables that are used must be initialized at some point.
public void example(){
String name;
if(name == null) return null;
}
In the above example the variable name has not been initialized. There are several ways to solve this problem:
public void example1(){
String name = null;
if(name == null) return null;
}
This would solve the problem.
This would also solve the problem
public void exapmle2(){
String name = "";
if(name == null) return null;
}
Make the condition whether or not a file is provided. For example, if a file is provided, create the buffered reader and set line immediately. Otherwise, create a scanner and set the line.
Related
I'm not very familiar with File & Scanner objects so please bear with me:
I'm attempting to have a scanner look through a file and see if a specific string exists, then return true/false - I thought there would be a method for this but either I'm reading the docs wrong or it doesn't exist.
What I'm able to come up with is the following but I'm sure there's a simpler way.
public boolean findString(File f, String s) throws FileNotFoundException {
Scanner scan = new Scanner(f);
if(scan.findWithinHorizon(s, 0) != null) {
return true;
} else {
return false;
}
}
Well, there are many ways to check whether a certain file contains a certain string, but I can't think of a single method which opens the file, scans for the given pattern and then returns a boolean indicating whether the pattern has been found within the file.
I think that use-case would be to small, as in many cases, you want to do more with the contents than only searching whether it contains a specific pattern. Often you want to process the file contents.
Regarding your code, it is already fairly short. However, I would change two things here. First, as scan.findWithinHorizon(s, 0) != null already is a boolean expression, you could immediately return it, instead of using if-else. Second, you should close the file you opened. You can use the try-with-resources construct for this.
Here is the updated code:
try (Scanner scan = new Scanner(f)) {
return scan.findWithinHorizon(s, 0) != null;
}
Note that this code finds a pattern. If you want to find a literal string, then use scan.findWithinHorizon(Pattern.compile(s, Pattern.LITERAL), 0).
More on finding a pattern in a file: this Stack Overflow post
More on try-with-resources: Oracle Java documentation, Baeldung
I would use a while-loop and simply use indexOf to compare the currentLine to your string.
public boolean findString(File f, String s) throws FileNotFoundException {
Scanner scan = new Scanner(f);
String currentLine;
while((currentLine = scanner.readLine()) != null) {
if(currentLine.indexOf(s)) {
return true;
}
}
return false;
}
An advantage of doing it this way is that you can also have an integer which you increase with every run of the loop to get the line in which the string is included (if you want/need to).
I get a lot of this anomaly. Here BufferedData ist marked as DU' anomaly by PMD. What is wrong with this approach?
private static void summUpBuffer(BufferedReader in) throws IOException {
List<String> bufferedData = new ArrayList<>();
for (String line = in.readLine(); line != null; line = in.readLine()) {
bufferedData.add(line);
}
}
'DU Anomaly' means the code might not do what you intended. Since you never use the variable bufferedData, it is flagged up due to being a pointless assignment.
In essense your method doesn't do anything. All its side effects are local and will be forgotten as soon as the method returns.
Complete the method and the warning will most likely go away.
Edit: Actually there is one side-effect, namely the reading of the BufferedReader. That's probably why bufferedData is the only thing flagged in this way.
I noticed that in the below example code, when the "Scanner scan" and "String [] words" were declared, they were assigned 'null'. Why do we need to do that? Many thanks for your help! * The example code was designed to read strings from a file, with the first line of the file being the number of strings: int howMany.
int howMany;
Scanner scan = null; //why do we need to assign a 'null'?
File f;
String[] words = null; //why not use String[] words= new String []; ?
try {
f = new File(filename);
scan= new Scanner(f);
howMany = scan.nextInt();
words = new String[howMany];
for (int i = 0; i < howMany; i++) {
words[i] = scan.next();
}
} catch (IOException e) {
System.out.println(e);
}
For the first question, why initialize the Scanner to null? Assume you didn't. In your code example, this wouldn't matter much, but what if you wanted to use the Scanner object after the try block, in the catch or finally blocks, or return it from method? The Scanner might not have been initialized, since you (and the compiler) doesn't necessarily know what will happen in the try block until runtime. It's not a necessity to instantiate the Scanner to null, it is just common place to instantiate IO objects to null outside of try blocks because you will usually have to do something with that IO object outside of the try block, namely, close it.
Secondly:
"why not use String[] words= new String []; ?"
Because array initializers require an amount between the '[' and the ']' and the amount is derived from the scan.nextInt(); execution line. Why is it being initialized to null? Se the first paragraph.
It is a good philosophy/strategy to not declare objects until they are needed to limit scope, and as an extension, it is good not to initialize objects until needed. Setting either of these to null preemptively will cause more harm than good and opens you up to NPEs. Java will initialize array components, class variables and instance variables to null by default. If the variable does not fall into this category, then leave it uninitialized unless the first paragraph situation forces you to do otherwise, as the compiler will warn you if it is used without being first initialized (this is a protective mechanism for you, the developer)
So to answer your question, you don't need to do that in the given example, and probably shouldn't.
Let me clarify the question I am asking. I have a java program I am working on that takes input from the keyboard via a readline library called JLine2. The library takes the entire line types as a command instead on breaking it up into space separated commands and arguments. What I am looking for is a safe way to break up the string that is passed as input.
I have tried using an array but since I am in the early stages of concept I don't yet know how many arguments my largest command will have so using a pre-initialized array I don't think will work. The problem I have ran into is when I check for null values in the array or when I check to see if a particular command or argument is present. Java keeps throwing an exception about the array index being out of scope or something. Because the array does not actually have a value for say array index 1 which is an argument to command in array index 0.
So what I am looking for is a way to take a string and safely split it into parts without having Java yelling at me when and array exception has occurred.
Here is the very slim code I can provide...
ConfigShell.class
package shell;
import java.io.IOException;
import configFS.ConfigFS;
import jline.console.ConsoleReader;
public class ConfigShell {
private ConfigFS config;
public ConfigShell() throws IOException {
config = new ConfigFS();
}
public void init() throws IOException {
ConsoleReader console = new ConsoleReader();
// When the program starts we want to be placed at / (root).
console.setPrompt(">> ");
// In this case an infinite loop is better than a loop based on whether line is equal to null.
// This allows line to be equal to null and still stay inside the shell.
while (true) {
String line = console.readLine();
if (line != null) {
// If pre-initialize the array I can check for null as a value for an array index.
// If I did this at time I needed the array and there were not enough index occupied the system would return an exception.
String[] cmdArgs = new String[4];
// We need to split up the incoming line because JLine2 does not do it for me.
// This allows me to evaluate the entire command piece by piece rather all at once.
cmdArgs = line.split("\\s+");
if (cmdArgs[0] != null && cmdArgs[0].equals("add")) {
if (cmdArgs[1] != null && cmdArgs[1].equals("server")) {
if (cmdArgs[2] != null) {
config.addServer(cmdArgs[2]);
System.out.println("Added server " + cmdArgs[2] + " to the configuration successfully.");
}
}
}
if (cmdArgs[0].equals("exit")) {
System.exit(0);
}
}
}
}
}
Note for testing: My Start.class main method makes a call to the init method in the above file.
You can do:
String cmdArgs = line.split("\\s+");
and then, before accessing any particular index, check the size of the array so that you do not get ArrayIndexOutOfBoundException
Something like this:
if(cmdArgs.length>=2){
//It means you have at least 2 elements
//Now its safe to access cmdArgs[0] and cmdArgs[1]
}
If all your problem is to have a storage for a variable number of strings you can use ArrayList<String> object.
You declare it like ArrayList<String> as = new ArrayList<String>();
Then when you split something from your command string you will simply use add method:
as.add(yourString);
If you need to retrieve a particular element of the ArrayList you can use its get method:
as.get(0);
You can process all elements with for each loop:
for(String str: as) {
println(str):
}
Have a look here for info and here for an example.
As I think you can use StringTokenizer class and its methods for your requirement.
see the sample code below:
if(line!=null)
{
StringTokenizer st=new StringTokenizer(line);// by default it takes space as delimiter....you can use as required as second argument in constructor...
while(st.hasMoreTokens())
{
String token1=st.nextToken();
// do your stuffs here..........
// I don't know exactly about your required logic here......
/* if(token1.equals("add"))
{
String token2=st.nextToken();
if(token2.equals("server"))
{
String token3=st.nextToken();
config.addServer(token3);
System.out.println("Added server " + token3 + " to the configuration successfully.");
}
}
*/
}// while closing...
}// outer if closing...
Or as PM 77-1 told you can use ArrayList. But as my opinion LinkedList should be a better option here.
I have this line code:
String name = Book.getName();
/*next lines of code*/
Next, variable name processing in other code without any checks.
In some cases, possible situation, when name=null and other code will exit with an error.
It is bad.
Also, I cant access to the other code.
So, what do you think, my next implementation is correct:
try
{
String name = Book.getName();
if(null== name)
throw new NullPointerException("method 'getName' return null");
/*next lines of code*/
}
catch(NullPointerException e)
{
System.out.print("Hey! Where book name? I exit!");
System.exit();
}
I have any other choose in this case?
It is possible to generate any other type of Exception or only NullPointerException?
Thanks.
Edit:
Ok,
String name = Book.getName();
it's imagine code line. In real case, I have more complex code:
List<Book> bookList= new ArrayList<Book>();
String name = null;
Iterator i = BookShop.getBooks.iterator(); //BookShop it is input parameter!
while(i.hasNext())
{
Book book = (Book) i.next;
name = book.getName();
nameList.add(name);
}
This example more full.
So, in this code input parameter BookShop Object.
What problem I can have with this Object?
BookShop can be NULL;
method BookShop.getBooks() can return NULL;
Also, getName() can return NULL too.
So, general problem next: there is no guarantee the correctness of input parameter BookShop!
And I must to consider every possible option (3 NULL)
For me, add General try-catch block and that all.
No?
You can create any exception you like by extending the Exception class, like a NoNameProvidedException for example. There are a lot of example one Google to help you do that.
I guess in your case just checking with an if if the name is null should be sufficient as you just want to do a System.exit().
Your code is a bit iffy, but I assume you're learning. You don't need to throw the NullPointerException explicitly, you can throw whatever Exceptions you like.
But you probably don't really need the Exception catching here, you can just check for the null and handle the situation appropriately if it's true.
Also, please avoid Yoda conditions. Your if statement should read
if name is null
so
if (name == null)
I would probably use IllegalStateException:
String name = Book.getName();
if (name == null) {
throw new IllegalStateException
("Method foo must not be called when the book has no name");
}
It really depends on where the state is coming from though - it's not really clear what's going wrong here.
I certainly wouldn't start catching NullPointerException - exceptions like that (and the illegal state one) shouldn't be explicitly caught. Let them bubble up, and if it's appropriate have some sort of top-level handler.
Exceptions should not be used for normal control flow. Just use the if block:
String name = Book.getName();
if (name == null) {
System.out.print("Hey! Where book name? I exit!");
System.exit();
}
/*next lines of code*/
Using try and catch in this case is unneeded. You can just write like this:
if(Book.getName() != null)
String name = Book.getName();
else
//handle the situation with null
You don't need to throw an Exception in this case - just handle the null value and you are fine.
It's more friendly for Java not to use exceptions, but just check the return value
String name = Book.getName();
if (name == null)
System.out.print("Hey! Where book name? I exit!");
else {
/*next lines of code*/
}