I have the code:
public class RssReader {
private File dataFile = new File("data.dat");
private FileInputStream dataStream = new FileInputStream("data.dat");
boolean fileExists;
public static void main(String[] args) {
}
}
My question is, can I put FileInputStream or any code that requires Try/catch as a global function?
Yes you can. you can declare that main method throws an Exception of any kind, i.e.
public static void main(String[] args) throws IOException {
}
And you can omit the try-catch block in the code.
I would highly suggest NOT doing that, though. First of all, try-catch blocks exist for a reason. They are here to catch exceptions that you might foresee but have no control of (i.e. bad file format). Second of all, they will let you close the streams in finally blocks even if the exception happens.
Yes you can if you let your constructor throws the exception :
class RssReader {
private File dataFile = new File("data.dat");
private FileInputStream dataStream = new FileInputStream("data.dat");
boolean fileExists;
RssReader()throws IOException{}
}
Then each time you will construct a new RssReader object, the method that handle this construction should throws it too (like darijan said), or you can create a try-catch block in this method :
public void someMethod() throws IOException {
RssReader r = new RssReader();
}
or :
public void someMethod() {
RssReader r;
try {
r = new RssReader();
} catch (IOException e) {
e.printStackTrace();
}
}
You may add that code by signing the method with throws Exception. But it is not recommended when you have an stream reader or something like that because often you gotta close the stream or flush the writers.
I think you should think about it when you need to open or close a stream object.
There are several things you can do and several you can't:
You can't initialize a variable with code that can throw a checked exception. The compiler will complain. So your line beginning private FileInputStream ... is illegal.
You can't use the instance variables inside the static main() method. The compiler will again complain once you put ... dataStream ... inside main().
You can put a throws IOException on the main method.
One way to deal with these things is to do this:
public class RssReader {
public static void main(String[] args) throws IOException {
File dataFile = new File("data.dat");
FileInputStream dataStream = new FileInputStream("data.dat");
boolean fileExists;
... use the variables here ...
}
}
which will toss you out to the command line if you run the program and, for example, the file doesn't exist. An error message and stack trace will be printed if that happens.
What I did up there is move all the variables into the scope of the main() method. Then I added the throws on the method so it will let whatever basic part of Java calls main() handle the exception.
Or you could do something another way like this:
public class RssReader {
private static File dataFile = new File("data.dat");
private static FileInputStream dataStream;
static {
try {
dataStream = new FileInputStream("data.dat");
} catch (IOException e) {
throw new RuntimeException(e); // this isn't a best practice
}
}
static boolean fileExists;
public static void main(String[] args) {
... use the variables here ...
}
}
which will do the same thing if there is a problem with finding the file. Out to the command line and print messages.
This hides the possible checked exception inside a static initializer block with a try-catch around it. The checked exception is turned into an unchecked exception. It also makes all the variable static so they can be used in the static method main()
One more possible solution that's an even better way:
public class RssReader {
private File dataFile = new File("data.dat");
private FileInputStream dataStream;
boolean fileExists;
public RssReader() throws IOException {
dataStream = new FileInputStream("data.dat");
}
public void doTheWork() {
... use all the variables here ...
}
public static void main(String[] args) {
try {
reader = new RssReader();
reader.doTheWork();
} catch (IOException e) {
System.out.printf("File 'data.dat' not found. Exiting ...");
}
}
}
which is the one I like best. It gives you control over what happens if an exception happens so we print an informative message and tell them the program is finished. All the variables are instance variables inside the object instance created in the main() method. Main does almost nothing but create the instance and tell it to get to work. Main also decides what to do if it fails.
The changes are to move everything to instance scope and out of static scope, except catching the fatal exception. You can leave your variables at the top where they are easy to read. The method that does the work is given a name to describe what it does.
Related
I have a set of Java files in the same package, each having main methods. I now want the main methods of each of the classes to be invoked from another class step by step. One such class file is Splitter.java. Here is its code.
public static void main(String[] args) throws IOException {
InputStream modelIn = new FileInputStream("C:\\Program Files\\Java\\jre7\\bin\\en-sent.bin");
FileInputStream fin = new FileInputStream("C:\\Users\\dell\\Desktop\\input.txt");
DataInputStream in = new DataInputStream(fin);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine = br.readLine();
System.out.println(strLine);
try {
SentenceModel model = new SentenceModel(modelIn);
SentenceDetectorME sentenceDetector = new SentenceDetectorME(model);
String sentences[] = sentenceDetector.sentDetect(strLine);
System.out.println(sentences.length);
for (int i = 0; i < sentences.length; i++) {
System.out.println(sentences[i]);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (modelIn != null) {
try {
modelIn.close();
} catch (IOException e) {
}
}
fin.close();
}
}
I now want this to be invoked in AllMethods.java inside a main method.
So how can I do this? There are several other class files having main methods with IOException which have to be invoked in AllMethods.java file.
Update -
I have main methods having IOException as well as main methods not having IOEXception that has to be invoked in AllMethods.java.
You can do that. Main method is also just like any other static method
public static void main(String[] args) throws IOException {
....// do all the stuff
Splitter.main(args); // or null if no args you need
}
First of all, what you should probably do is refactor your code so each main method calls some other method, and then AllMethods makes calls to those new methods. I can imagine there might be some cases where it's useful if you're just trying to, for example, write some test code, but usually you wouldn't want to call main methods directly. It's just harder to read.
If you want to try it though, it's pretty easy, you just call the main method like any other static method. I once in college wrote a web server where, to handle authentication, I recursed on the main method. I think I got a C because it was unreadable code, but I had fun writing it.
class AllMethods {
public void callsMain() {
String[] args = new String[0];
Splitter.main(args);
}
}
In the Main.java, the main method should add throws Exception as shown below:
package com.company;
import java.io.FileNotFoundException;
public class Main extends makeFile {
public static void main(String[] args) throws FileNotFoundException {
makeFile callMakeFile = new makeFile();
makeFile.main(args);
// cannot figure out how to call the main method from the makeFile class here...
}
}
I'm not great with java terminology so it will be easier for you to understand via example:
I instantiate a mymethods class from a
Main class:
public class Main()
{
public boolean hasErrors = false;
MyMethods m = new MyMethods(); //cannot use try/catch
public static void main(String[] args){
m.writeToFile("text");
}
}
In the above class, i cannot (i tried) use a try catch to catch a manually thrown FileNotFoundException but apparently such methods cannot be used in that location (wrapping MyMethods m... in try/catch). I had tried to throw that error when my requisite file wasnt found
MyMethods:
public class MyMethods()
{
public MyMethods(){
if(!new File("file.txt").canWrite()){
changeSuper(true);
throw new FileNotFoundException();
}
}
public void changeSuper(boolean b) //does not work
{
super.hasErrors = b;
}
//input more methods etc here
}
Why is it not possible to use try/catch?
How can i report a filenotfound to the main method?
Note that this is from a GUI app in netbeans, but is not the focus here. Program will not compile if try/catch wraps that line
(note to admins/mods: this question needs butchering, but I cannot express my question better myself)
You just need to add the throws keyword to your method, i.e:
public static void myMethod() throws FileNotFoundException{
// Code goes here ...
if( fileNotFound )
throw new FileNotFoundException("File not found.");
}
you can then catch the exception by surrounding your call to the method with a try/catch block:
try {
// Do stuff...
myMethod();
} catch (FileNotFoundException ex){
// Handle error, if thrown...
}
I am currently writing a Text Editor using linked lists, and I am pretty much done but I come across a FileNotFoundException when trying to test my program's command line, even though I declared it to be thrown.
Here is the skeleton for my Editor:
public class Editor {
public Editor() {
}
public void commandLine() throws FileNotFoundException {
}
}
Here is the driver for my program:
public class EditorTest
{
public static void main(String[] args)
{
Editor asdf = new Editor();
asdf.commandLine();
}
}
I am still getting an error for an unreported FileNotFoundException even though I declared it to be thrown in my command line method. What is wrong?
You need to add throws FileNotFoundException to your main method. Or, you can add:
try {
asdf.commandLine();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
to your main method, depending on what you need to do based on that exception.
Yo need to declare it on main, too
public static void main(String[] args) throws FileNotFoundException {
Declaring an Exception to be thrown in a method (i. e. using throws MyException) doesn't prevent the exception to be thrown, it rather allows the method to throw it for a caller of that method to have to catch that Exception
I'm trying to have the file "TutorialMap" used as the map in this TutorialMission. I keep getting told that the MapReader "reader" needs to be static, but when it's static, I get told "Unhandled exception type FileNotFoundException" with the error on the constructor of reader.
static MapReader reader = new MapReader("TutorialMap");
static Territory[][] missionMap = reader.getMap();
public TutorialMission() throws FileNotFoundException {
super(missionMap, Size, AircraftCarrierID, AircraftCarrierID);
}
The Super class' constructor:
public class MissionIF extends Map {
public MissionIF(Territory[][] load, String size, int StartingMoney, int powerLevel)
{
// Set money per mission.
super();
Thanks for your time.
I don't know why it must be static, but since the constructor throws the checked exception, it has to be handled at the place of calling. Therefore do something like this:
static MapReader reader = null;
static Territory[][] missionMap = null;
static {
try {
reader = new MapReader("TutorialMap");
} catch(FileNotFoundException e) {
e.printStackTrace();
}
missionMap = reader.getMap();
}
Compiler requires your reader to be static because you invoke it when initializing other static variable missionMap.
When you mark it as static compiler is going forward and sees that you do not catch exception thrown from your constructor TutorialMission.
Since I do not understand what do you really want to do I can just suggest you:
If you want all this stuff to be static initialize reader into static initializer and catch exception:
static MapReader reader;
static {
try {
reader = new MapReader("TutorialMap");
} catch(FileNotFoundException e) {
throw new IllegalArgumentException(e);
}
}
Your checked exception is now wrapped by unchecked one.
Alternatively (if you do not really want to hold this data in static variables just remove static modifier and perform initalization in constructor:
public TutorialMission(MapReader reader, Territory[][] missionMap) throws FileNotFoundException {
super(missionMap, Size, AircraftCarrierID, AircraftCarrierID);
missionMap = reader.getMap();
}
Now caller is responsible on creating and passing here the reader.
surrounds the code throwing "Unhandled exception type FileNotFoundException" with try catch block. Your are getting this exception because its a checked exception and you are forced to handle this. i would suggest using IDE like eclipse(if you are not using this already) which is really helpful for development.
try {
reader = new MapReader("TutorialMap");
} catch(FileNotFoundException e) {
throw new RunTimeException(e);
}
I have something like this:
public static final String path;
static {
path = loadProperties("config.conf").getProperty("path");
}
public static void main(String... args) {
// ... do stuff (starting threads that reads the final path variable)
// someone want's to update the path (in the config.conf file)
restart(); // ???
}
I want to reinitialize the JVM calling the static initializer again, and then main(...)!
Can it be done?
You can start your application using a custom class loader, this will allow you to load and unload your static variables.
However, basically its a very bad design to need to do this. I like making fields final, but you shouldn't make them final if you want to change them.
If your goal is simply to reload some configuration files, why not implement a file change monitor?
Here's a good tutorial on this subject:
http://download.oracle.com/javase/tutorial/essential/io/notification.html
I think what you're proposing (restarting your application automatically) would be a little more cumbersome than just watching for file updates.
A simpler approach is simply not to use the static initializer for this. Why not just make path non-final and load it in main?
I'm accepting Peter Lawrey answer but post a complete example for anyone to use!
I'm not going to use this in production code... there are other ways of doing it!
public class Test {
public static void main(String args[]) throws Exception {
start();
Thread.sleep(123);
start();
}
private static void start() throws Exception {
ClassLoader cl = new ClassLoader(null) {
protected java.lang.Class<?> findClass(String name)
throws ClassNotFoundException {
try{
String c = name.replace('.', File.separatorChar) +".class";
URL u = ClassLoader.getSystemResource(c);
String classPath = ((String) u.getFile()).substring(1);
File f = new File(classPath);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte buff[] = new byte[(int) f.length()];
dis.readFully(buff);
dis.close();
return defineClass(name, buff, 0, buff.length, null);
} catch(Exception e){
throw new ClassNotFoundException(e.getMessage(), e);
}
}
};
Class<?> t = cl.loadClass("Test$Restartable");
Object[] args = new Object[] { new String[0] };
t.getMethod("main", new String[0].getClass()).invoke(null, args);
}
public static class Restartable {
private static final long argument = System.currentTimeMillis();
public static void main(String args[]) throws Exception {
System.out.println(argument);
}
}
}
how about this structure
public static void main(String... args) {
boolean restart = true;
while (restart )
{
retart = runApplication();
}
}
If you ever detect the need to restart you application, have runApplication return true.
If it is time to exit return false;
If you have an UI or a daemon so you can control output to stdout, you can make a wrapper on the outside that starts your program.
If the program upon exit outputs "RESTART" you can restart your program again from this wrapper. If not, it just ends.
Or if you want the pure java way, you can go with a solution with classloaders as Peter Lawrey mentioned in his post. Before going down this route you should really rethink your design (if it is your code) and make your code capable of cleaning itself up.