I am learning java programming. Do I have to write BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); again and again in every method in which I have to take input from user? If some other alternatives exist, kindly suggest them.
Probably you should think more carefully at the design of your application.
Usually separating the interaction with the user and the logic of your application is a very good idea.
Ideally you will have a class encapsulating both a BufferedReader and something to print to the console and providing methods to get the input you need and to show the user the information he should be aware of.
In order to have this work you will have to create a new instance of that class and pass it to all the classes that need to interact with the user.
In this way you clearly separate the distinct concerns of your application and this separation will improve the maintainability of your application. Think for instance what would happen if you are required to write a graphical user interface in addition to the textual user interface.
Depending on your use case, there are two possible answers:
If you are using the output stream for debugging, do whatever you like (as long as it works for you), it's your code. Other user's answers are suitable for this.
If, however, you are using it for the actual program, you should do one of the following:
Pass the output stream as a parameter to each method that will use it, or
Have each method return a string that the main program will output.
For major input/output methods, like a 'prompt user for input until they input a valid value', you should pass the stream as a parameter, like so:
Incorrect:
public static void main(String[] args){
promptUserForInput();
}
public static int promptUserForInput(){
Scanner in = new Scanner(System.console().reader());
PrintWriter out = System.console().writer();
out.print("Enter an integer:");
// [...]
}
Correct:
public static void main(String[] args){
promptUserForInput(System.console());
}
public static int promptUserForInput(Console io){
Scanner in = new Scanner(io.reader());
PrintWriter out = io.writer();
out.print("Enter an integer:");
// [...]
}
The other case, where the method does not need live interaction with the user, it should return a String object that the interaction methods will use.
Incorrect:
public static void main(String[] args){
printMsg("bob", "tuna fish", "pickles", "rye");
}
public static String printMsg(String person, String type, String topping, String bread){
System.out.printf("%1$s wants a %2$s sandwich with %3$s on %4$s bread%n",
person, type, topping, bread);
}
Correct:
public static void main(String[] args){
System.out.println(generateMsg("bob", "tuna fish", "pickles", "rye"));
}
public static String generateMsg(String person, String type, String topping, String bread){
return String.format("%1$s wants a %2$s sandwich with %3$s on %4$s bread",
person, type, topping, bread);
}
There is one other improvement, and this I think reaches more to the point of your question. You can create a factory class to instantiate your readers and writers for you:
public class InputFactory {
public static InputStreamReader inStreamReader(InputStream in){
return new InputStreamReader(in);
}
public static BufferedReader bufferedReader(InputStream in){
return new BufferedReader(inStreamReader(in));
}
public static Scanner scanner(InputStream in){
return new Scanner(inStreamReader(in));
}
}
You can add as many overloads to that as you like, so you can call just one function to construct the desired input stream type from any input stream, or even other potential input sources, like files. To get a BufferedReader from an InputStream, call InputFactory.bufferedReader(myInputStream). While that still is a little long, the auto-completion features in eclipse can help enter it quickly, which it won't do as well if you just use the chained constructors.
It depends, you can pass it as a argument to your methods or make it class atribute like
public class Something {
private BufferedReader reader = new BufferedReader(new InputStreamReaddoinger(System.in));
}
or even make it public static variable in order to access it from other classes
public static BufferedReader reader = new BufferedReader(new InputStreamReaddoinger(System.in));
You can make it a static variable:
public static BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
and access it from each relevant method accordingly.
Also, take a look at Scanner, a utility class that makes reading input from the user easier.
As #mariosangiorgio points out, it is important to take into consideration what parts of your program are doing what. You should generally split up your code into logically consistent chunks, and this means separating code that deals with I/O from code that deals with core logic. Consequently, when designing any serious application, the static-variable approach might not be the best one as it could undermine this philosophy of "code separation" in certain contexts. Nevertheless, for someone who is just learning, it should pose no problem.
Related
I would like to write a general method readfile() to a class to use it on the subclasses to read all lines.
I have trouble with how to call methods from one class to another.
First, is it better to make void readfile() ?
or return a File?
Secondly, which is the way to reused from other classes?
Example of my code:
public class Reader{
Scanner myReader = new Scanner(myObj);
public void readFile(){
File myObj = new File("filename.txt");
Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
String data = myReader.nextLine();
System.out.println(data);
}
}
}
public class ReadContentOfFile extends Reader{
public List<String> parseFile{
List<String> name = new ArrayList<>();
//how to get lines? as I have them, from
another method?
//for example If I want to get the
words,separated, by comma
return name;
}
}
public void Main(){
}
For example for each line of a file, how I get each element.
My problem is about how to get the data for another method, for another class.
First, is it better to make void readfile() ? or return a File?
Depends on what you want to do with the output, since you are printing the contents to console then you don't have to return the file and void is OK.
But if you wanted to use this file after you call the readFile method then you must return it or set it to class member.
Secondly, which is the way to reused from other classes?
make your method static, so you can access it without creating an object since it's just a utility and object is not important here.
public static void readFile(){
//..
}
then do
Reader.readFile()
Please, do not use Scanner to read a file, there are simpler and better options.
First, a File itself it's nothing but a reference and it won't contain any content
related to the file on system. So, you can consider to return a File object only if you may need some information from the file-system about privileges, existence, perform deleting actions or retrieving path information.
Usually when i write methods to read() or save() a file i make them void.
About how do you read data and access it, in java there are a lot of possibilities.
I'll show you one pretty straightforward:
List<String> lines = Files.readAllLines(Paths.get("filename.txt"), StandardCharsets.UTF_8);
And that's it but there are more options.
I tried this code but its not working
import java.util.*;
class StringBuffer
{
public static void main(String[] args)
{
StringBuffer Name1=new StringBuffer();
Scanner in=new Scanner(System.in);
System.out.println("Enter a string: ");
Name1.append(in.nextLine());
System.out.println(Name1);
}
}
If the StringBuffer is per-defined then its works. But it fails to take input from user.
You are using class StringBuffer which is already a built-in class in Java.
Ref: Oracle doc
When you instantiate an object like StringBuffer Name1=new StringBuffer(); within your custom defined class StringBuffer, then it creates an object with reference to your custom defined class StringBuffer.
You need to create an object of Java's inbuilt StringBuffer class.
Change your class name to something else or use StringBuilder which is not thread safe but faster than StringBuffer.
Additionally, using Scanner class to read your input.
How can I read input from the console using the Scanner class in Java?
your code is correct but the class name is wrong. change your class name and run it.
StringBuffer is a predefined class in java.lang package which you are trying to use but as the name of your class clashes with it, it uses your class definition instead of the predefined one.
Here Name1.append(in.nextLine()); you are calling append method which is not implemented by your class hence will raise an error cannot find symbol.
Change your class name to something unique and you are good to go. Nothing wrong with the input.
no need to change your class name wheather it's StringBuffer or not.
But do one change in your class. Surely it'll take input from user side
public class StringBuffer {
public static void main(String[] args) {
java.lang.StringBuffer Name1 = new java.lang.StringBuffer();
Scanner in=new Scanner(System.in);
System.out.println("Enter a string: ");
Name1.append(in.nextLine());
System.out.println(Name1);
}
}
It will solve your problem.
I'm very new to Java, and this is probably a very dumb question. I'm trying to get a simple input from the user, and to do that I get the Scanner class, or BufferedReader. Yet when I try to import java.io.*, the classes show up undefined.
Here's my code:
package testing;
import java.io.*;
import java.util.Scanner;
public class Something {
public static void logln(String content) {
System.out.println(content);
}
public static void main(String [] args) {
}
void getInput(String prompt) {
Scanner s = new Scanner();
}
}
Scanner s is showing up undefined. Why might this be?
Here's your problem:
Scanner s = new Scanner(); // no constructor exists
You need to pass a parameter into the Scanner constructor as this class does not have a default no-parameter constructor. You will want to read the error message critically as it will often tell you exactly what is wrong, here that "The constructor Scanner() is undefined".
If you have similar questions in the future, always post the exact and complete error message.
Also, get real friendly with the Java API as it will help you understand the classes that you're using. Here the Scanner API will tell you exactly what constructors are available for this class.
Hovercraft Full Of Eels, has pointed to the correct error.
I would like to add a couple of things -
the correct constructor would be
Scanner s = new Scanner(System.in);
Also I don't quite understand why your getter method, getInput() is parametrized. Would you like to elaborate on that?
Your problem has nothing to do with java import.
If you want to take input from inputStream which is typically connected to keyboard input, change your constructor to
Scanner sc = new Scanner(System.in);
Read the entered input using,
String content = sc.nextLine();
I am calling a method from a class and it gives me an error to make the method static. I am confused about why, as I asked this question What's the difference between a class variable and a parameter in a constructor? and my understanding was that class variables were made static.
Patient class:
public String setOption(String option) throws IOException
{
option = stdin.readLine();
//stuff here
return option;
}
Patient management system:
public class PatientManagementSystem
{
static BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in));
public static void main(String[] args) throws IOException
{
Patient.setOption(null);
}
}
The error:
Do I change the method to static or create a local variable?
Based on your earlier question, I think may not be fully digging the concept of the local variable. In this method:
public String setOption(String option) throws IOException
{
option = stdin.readLine();
return option;
}
option is a local variable. You pass the initial value for that variable as an argument to the setOption method each time you call it (and you happen to ignore that value), but with that detail out of the way, this is the same as
public String setOption() throws Exception
{
String option = stdin.readLine();
return option;
}
Now, local variables are something completely different from instance or class variables: they are valid only within a method body, and exist only during the time that method is executing. With that in mind, let's look at this code:
static BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in));
public static void main(String[] args) throws IOException
{
Patient.setOption(null);
}
Here you are basically misusing a class variable stdin for something which should have been a local variable:
public static void main(String[] args) throws IOException
{
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
Patient.setOption(null);
}
On to the question of your method call... setOption is currently an instance method, which means it must be called in the context of an instance. You are calling it as-is, with no instances of Patient involved. If you continue down this road, you won't be able to represent more than a single patient, probably not your idea. So you want to keep the method as it is and create an instance of Patient:
Patient p = new Patient();
p.setOption(...);
In your overall design it is not clear what role setOption should play, but it is not a good idea that it uses the static stdin variable (I already made it local above). You want to pass any data read from stdin into the setOption method and thus decouple it from the input reading logic.
You (probably) need to create an object of the Patient class.
Patient myPatient = new Patient();
myPatient.setOption(null);
It's hard to necessarily know what you want to do with such limited information. I don't know what you intend to do with the Patient class, but my best guess? It makes sense to do it this way, given you're trying to call a method with a setter naming convention.
If you don't intend to instantiate an object and go the route of making setOption a static method, then you should probably change the method name.
With a more in-depth explanation of what exactly you're trying to accomplish (not even talking pseudo-code, just a very abstract idea of what you're trying to do), it would be easier to explain more about static here (with your specific example) and what you should be doing, etc.
Do I change the method to static or create a local variable?
Both is OK.
If your method doesn't use class variables, it's better to make it static, so you do not have to instantiate the class for the method call.
The question of when to make something static vs. non-static is based on the real-world object/concept being modeled. Let's take the example of the Patient object in this code. Without seeing any code about the Patient, it's still pretty clear what a Patient is and what it represents. So, at its simplest:
If you're doing something with a particular Patient (let's say Jane Doe), then it's not static. It's operating on an instance of a Patient.
If you're doing something regarding the concept of a Patient, then it's static.
So some non-static operations might be:
Update the Patient's name
Admit/discharge the Patient from a hospital
Transfer the Patient to a different Doctor
All of these would involve a specific Patient, which would have been initialized somewhere:
var janeDoe = new Patient("Jane Doe");
// ...
janeDoe.TransferTo(doctorSmith);
I'm actually having trouble thinking of some static methods for a Patient. The most common example of a static method is probably a factory method, where you get an existing Patient or collection of Patients. Something like:
var janeDoe = Patient.Fetch("Jane Doe");
or:
var todaysPatients = Patient.Fetch(DateTime.Today);
Various helper methods are often static as well, perhaps a method on the Patient object which accepts a MedicalRecord object and converts it to a different format, for example.
But the overall idea is the same. If you're interacting with a specific instance of an object, then you need an instance of that object to represent that real-world concept.
Because you are directly calling that method without creating object of class.
When to have static methods?
To call a method in a static way, you have to make it static :
public static String setOption(String option) throws IOException
But in your example if stdin is not a static member of your Patient class, it can't work.
To sum up, you can call a method the way you call it when it's declared static. In a static method you can access only static members of your class.
Try this in your main method :
Patient myPatient = new Patient();
myPatient.setOption(null);
We create classes with static methods when we intend to use those methods as utility methods, like parseInt in the class Integer. thus either modify the method
public static String setOption(String option) throws IOException // STATIC
{
option = stdin.readLine();
//stuff here
return option;
}
and then use the method like
Patient.setOption(null);
OR instantiate an object for Patient like
Patient obj = new Patient();
obj.setOption(null);
In Java main method is special. It's the starting point of your code. Static methods could be called from anywhere in your code. Thus actually it does not belong to the containing class. It's also true for the main method.
Thus you should construct your object in the main method and then use the constructed instance's methods. If you do not construct your an instance, then your ide will recognise the error and suggest you to make it static.
UPDATE:: OK i am putting the original problem statement here
Given the Main class create a method createPerson and call it in any other method more than once, then on the basis of the number of times the createPerson has been executed you have to initialize the objects and input names of students and output the names.
once i come to know how many objects i have to create its quite trivial to program the later part
for the prior problem of finding the number of objects to be created i have chosen the way of file handling as i come from a C, C++ background where file handling is comparatively simple.
now how should i modify the program such that i write an integer in the file, and later when i will read the file i will get the number of objects
this example forbids the use of static variable, it is a sort of brain teaser
so do Not use static
this is my Main.java file
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException{
int i;
Student[] totalStudents = new Student[10];
Student.create3Persons();
Student.create2Persons();
}
}
and this is my Student.java file
import java.io.*;
public class Student {
private static void createPerson() throws IOException{
int number=0;
File file = new File("arg.txt", null);
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
while(dis.readInt()!= -1)
{
number++;
dos.writeInt(1);
}
}
static void create2Persons() throws IOException{
Student.createPerson();
Student.createPerson();
}
static void create3Persons() throws IOException{
Student.createPerson();
Student.createPerson();
Student.createPerson();
}
}
How should i modify this program so that i calculate how many times has been the function createPerson being called??
If you want to calculate how many times a static method has been called, you have to use a static variable - it's genuinely global state. EDIT: Yes, you can use the file system as another repository for global state, but I'd personally say that's generally a bad idea - particularly if it's just to get round a requirement in an academic question.
I guess there are some exceptions to this - if the static method is provably only called from one class, and that class is a singleton, then there could be an instance method in that singleton... but that's pretty much a corner case. In your case, create3Persons and create2Persons are both accessible from anywhere in the package, and they aren't instance methods in a singleton, so therefore there's no single context in which to keep the call count except a static variable.
Perhaps if you could explain a bit more about what you're trying to achieve, we could help you more...
EDIT: Yes, if you can rely on cooperative callers - and you can change the method signatures - then you could keep (say) an AtomicInteger, and make sure you always pass a reference to the same object into the createStudent method. Again, we'd really need to know what the rules of the question are...
i have to disagree with #Jon Skeet, i dont think you have to use a static variable. Why not simply return the number of items created, and keep the total count in a local variable in your main method ? (assuming youre allowed to modifiy method signatures of course, otherwise youre stuck with the global variable solution) you seem to have an unused counter right there already, why not use it?
You can use:
synchronized(this){
System.setProperty("methodCounter",number++);
}
instead of a file based counter. And in the main method:
System.getProperty("methodCounter");
Use AOP (Aspect-Oriented Programming).
You can use a system property to store the quantity of calls...this way you don't have to use the file system or AOP or change method signature.
Mostly when we want to retain value across method, either we go for
Static variable
or pass the variable as reference
or pass the variable and return the updated variable and use it again
int createPerson(int counter);
i got the Solution
instead of file handling i am doing this
static int createPerson(int c){
return (++c);
}
static int create2Persons(int c) {
return Student.createPerson(Student.createPerson(c));
}
static int create3Persons(int c) {
return Student.createPerson(Student.createPerson(Student.createPerson(c)));
}
public static int create5Persons(int i) {
return Student.createPerson(Student.createPerson(Student.createPerson(Student.createPerson(Student.createPerson(i)))));
}
and in the main method i have initialised an integer and i do this
c += Student.create2Persons(i)-1;
c += Student.create3Persons(i)-1;
c += Student.create5Persons(i)-1;
System.out.println(c+"c is");
this saves use of files
how to tag the thread as answered?