I'm using constructor chaining, and I'm worried that it's causing a resource leak. Here are my two constructors:
/**
* Constructor to build the map based off of a file. Redirects to the Scanner-based constructor
* #param fileName the name of the file to open
*/
public GeoMap(String fileName) throws FileNotFoundException {
this(new Scanner(new File(fileName)));
}
/**
* Constructor to build the map based off of a Scanner. (Probably from an open file.)
* #param scanner the Scanner to read
*/
public GeoMap(Scanner scanner) {
// goes on to read the string data and make an object...
It's important that the object be created from any type of Scanner (keyboard, file, etc.), though it'll usually be from a file. The problem is that I think there's a resource leak going on here. Whenever I'm reading a file, I like to close it when I'm done. Problem is, the constructor chaining means that the this() call must be the first line. I'd be inclined to do something like this:
this(Scanner scannerToClose = new Scanner(new File(fileName)));
In my mind that would give me the name of a Scanner I could then close out. But that seems to really confuse the compiler--I get about 5 compile-time errors out of it, including a lot of "cannot find symbol" problems that imply that the compiler's just not wired for this sort of thing. Does Java support this? Or do I need to make a totally different initFromScanner() function that both constructors call? (Not elegant.)
Thanks.
Call scanner.close() at the end of your GeoMap(Scanner scanner) constructor.
This will close the Scanner created in GeoMap(String filename) since a reference to it is passed into the GeoMap(Scanner scanner) as scanner.
In essence, the scanner variable points to the new scanner that was created, so calling scanner.close() anywhere, in any method, closes it for any and all other methods it may be in the scope of.
Here is a program which demonstrates the object oriented nature of Scanners:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main
{
static class Test
{
String name;
public Test(String filename) throws FileNotFoundException
{
this(new Scanner(new File(filename)));
}
public Test(Scanner scanner)
{
name = scanner.nextLine();//body of constructor
scanner.close();
System.out.println("Your name is "+ name);
scanner.close();
/*These next lines of code show that the Scanner is closed */
String throwsException = scanner.nextLine();
System.out.println(throwsException + "here");//unreachable
}
}
public static void main(String[] args)
{
try
{
Test temp = new Test("input.txt");
}
catch(Exception e)
{
System.out.println(e);
}
}
}
input.txt:
Smitty
output:
Your name is Smitty
java.lang.IllegalStateException: Scanner closed
In essence it doesn't matter where the Scanner is created, if it is closed at any point, it is closed everywhere that it is in scope.
I assume that your issue is that you only want to close the involved scanner if you have created it in your constructor that takes fileName. I don't think there's anything wrong with your idea of having an init method that both of your constructors call. I don't think that's inelegant.
I think what I would do is create a third private constructor instead of an init method. It's really the same thing either way, although maybe at some point you'd want to be able to pass in a pre-built Scanner that you want closed at the end of the constructor call, in which case you could make this new constructor public so you could call it from the outside.
In either case, what I'd do is pass a boolean "closeScanner" parameter to the new constructor/method that indicates if the scanner should be closed or not. Here's my idea in code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
class GeoMap {
/**
* Constructor to build the map based off of a file. Redirects to the Scanner-based constructor
*
* #param fileName the name of the file to open
*/
public GeoMap(String fileName) throws FileNotFoundException {
this(new Scanner(new File(fileName)), true);
}
/**
* Constructor to build the map based off of a Scanner. (Probably from an open file.)
*
* #param scanner the Scanner to read
*/
public GeoMap(Scanner scanner) {
this(scanner, false);
}
private GeoMap(Scanner scanner, boolean closeScanner) {
// goes on to read the string data and make an object...
if (closeScanner)
scanner.close();
}
}
Lets start with this:
public GeoMap(Scanner scanner) {
...
}
Is there a resource leak here? Well, it depends on where the responsibility for closing the Scanner lies.
If responsibility lies in the constructor, then we can plug the leak like this:
public GeoMap(Scanner scanner) {
try (Scanner s = scanner) {
// original body
}
}
This is the ideal solution, but it assumes that the effect lifetime of the Scanner is the constructor.
If it is the caller responsibility, then the caller needs to deal with leak prevention. That is doable ... but outside of the scope of this question.
If it is neither the constructor or the caller's responsibility, then you need to treat the GeoMap itself as a resource, with all that that entails.
Now we consider this:
public GeoMap(String fileName) throws FileNotFoundException {
this(new Scanner(new File(fileName)));
}
Firstly, does new Scanner(new File(fileName)) present a potential resource leak?
In theory, yes. The Scanner constructor could open a stream for the file, and then fail, leaving the stream open.
In practice, it is highly unlikely. If we ignore bugs in the class library, and application bugs like using unrecognized character set names, the only cause of a spontaneous failure of new Scanner that could leak a file descriptor, etc is if you got an OOME. But that is likely to trigger a full GC anyway.
So what happens after that?
The answer depends on the earlier answer of where the responsibility lies in the GeoMap(Scanner) constructor.
If the responsibility lies in that constructor, we know how to avoid the leak; see above.
Otherwise ... we have problem:
There are possible solutions, but they may involve changing the way that the Scanner is used.
There may also be leaks involving the use of the that constructor directly.
In summary, depending on how you specify and implement GeoMap(Scanner), the GeoMap(String) constructor can be implemented to be leak proof in practice.
First, your class GeoMap should define how it handles a scanner that is given to it in the constructor; usually, when it is allowed to create its own Scanner instances as in your sample, the policy is that the GeoMap instance can do whatever it wants with that scanner, including closing it – this means it owns it, and ownership is transferred in the respective constructor.
If this is not the case (it does not own the scanner), you either have to drop the GeoMap(String) constructor (because, when not the GeoMap instance owns it, who else do and takes care of it later?), or you have to come to a design similar to that below:
class GeoMap
{
private final Scanner m_Scanner;
private final boolean m_MayCloseScanner;
/**
* Creates a GeoMap from a file.
*
* #param fileName The name of the file to open.
*/
public GeoMap( String fileName ) throws FileNotFoundException
{
this( new Scanner( new File( fileName ) ), true );
} // GeoMap()
/**
* Creates a GeoMap from a Scanner instance.
*
* #param scanner The Scanner to read
*/
public GeoMap( Scanner scanner )
{
this( scanner, false );
} // GeoMap()
/**
* Internal constructor.
*
* #param scanner The scanner to read.
* #param mayClose true, if this instance of GeoMap may close the
* given Scanner instance, false otherwise.
*/
private GeoMap( Scanner scanner, boolean mayClose )
{
m_Scanner = scanner;
m_MayCloseScanner = mayClose;
} // GeoMap()
…
}
// class GeoMap
Here the ownership is tracked by the flag m_MayCloseScanner.
Unfortunately, this does not yet solve your issue with the resource leak: the scanner will still not be closed, when the GeoMap instance is no longer used.
When your GeoMap instance will not own the scanner at all, you don't care, the resources taken by the scanner are a POOP (a problem of other people).
Ok, when you will need the scanner only for the initialisation of the GeoMap instance, you can have an init() method that closes the scanner when done:
…
public void init()
{
// Do something with the scanner ...
…
// Close the scanner when done.
m_Scanner.close()
} // init()
…
Of course, when GeoMap may or may not own the scanner, the closing line needs to look like this: if( m_MayCloseScanner ) m_Scanner.close;.
But if that init option does not work, you need a destructor for GeoMap instances. The concept of a destructor does not exist in Java, the closest to it was to implement finalize(), but this was deprecated some time ago (finally with Java 9), with good reason.
Have a look to this post on how to use Cleaner, PhantomReference and Closeable for your GeoMap class. It looks a bit confusing in the beginning, but reveals to be relatively straight forward in the end.
I have a simple java class as shown below:
public class Add2Numbers
{
public static void main(String[] args)
{
int num1=2, num2=4, sum;
sum = num1 + num2;
System.out.println("Sum of these numbers: "+sum);
}
}
I compile the class and run in matlab using:
obj = Add2Numbers;
javaMethod('main', o,"");
and I get the output: Sum of these numbers: 6 which is, of course, correct.
Next I change the code in my text editor (e.g. set num1=4) compile, execute the clear statements below:
clear all
clear java
clear import
clear CLASSES
clear ALL
clear
then run again:
obj = Add2Numbers;
javaMethod('main', o,"");
But the calculation result remains the same as before. If I close and restart MATLAB the modified java class runs correctly. So how on earth do I clear a java class without having to close MATLAB and restart it?
set
I am trying to find the square of a number using the scanner method but keep getting a
stackflow error. I am new to programming will be glad if someone helps me out.
My code is as below
import java.util.Scanner;
interface Number {
int findSqr(int i); // Returns the square of n
}
//a class A which implements the interface Number.
class A implements Number {
public int findSqr(int i) {
return findSqr(i);
}
}
public class Question5_1{
public static void main (String[] args){
A a = new A(); // an object of class A
// Reading a number from the keyboard
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.print(a.findSqr(i));
}
}
Fix the line which invokes the function recursively return findSqr(i) with return i * i as follows --
public int findSqr(int i) {
return i * i;
}
What you did there is an infinite recursion. The bit where it says
public int findScr(int i) {
return findSqr(i)
}
essentially calls the very same method an infinite number of times in the return statement.
What happens is, that you execute the method, and it tries to return an integer. What you wrote though is a return statement that "returns" another call of the same method, so it gets executed again. Then the whole thing starts over again, so you get a StackOverflow.
Since there is no other code present, I have no idea what you are actually trying to do, but the return findSqr(i) line is what causes the problem.
Initially, recursion may be a rather complicated subject to really wrap you head around, I suggest you either avoid it for now (although it enables you to solve many problems in a really elegant way) or try to understand it a bit better maybe. I'd suggest the Wikipedia article about recursion, although it gets complicated quite fast, or any other tutorial on it, just look it up on Google.
I am a bit lost here, i have been searching this for sometime.
I have a string $#897950%-1. Now i need to see if it contains a -1 in it. I tried
str.contains("-1") but it did not work. Can someone guide me to solve this ?
I tried it out as:
public static void main(String ar[]){
String str="$#897950%-1";
System.out.println(str.contains("-1"));
}
And See, what eclipse saw me, (It just work fine and gave me true as output):
Check whether you really have this string. May be debugger or output system replaces something.
I have the following code printing 'true'
public static void main(String[] args) {
String str = "$#897950%-1";
System.out.println(str.contains("-1"));
}
Maybe I'm forgetting an import at the head, but nothing seems to work. I'm trying to learn java and still beginner.
public class Main {
public static void main(String[] args) {
String s1=getInput("Enter First Number") ;
String s2=getInput("Enter second Number");
double d1=Double.parseDouble(s1);
double d2=Double.parseDouble(s2);
double result=d1+d2 ;
System.out.println(result);
}}
results in an error because the compiler doesn't recognize getInput("");
This is from Eclipse:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The method getInput(String) is undefined for the type Main
The method getInput(String) is undefined for the type Main
at Main.main(Main.java:8)
You're calling a getInput()-method which doesn't exist in your class. Have a look at this Java tutorial on I/O:
http://docs.oracle.com/javase/tutorial/essential/io/cl.html
"This is from Eclipse:
Exception in thread"
Eclipse should have warned you about this before you compiled the file with a "red" marks. Please fix them before compiling the class.
That is because getInput is not defined. Take a look at this example to see how to get input from a user.
http://www.roseindia.net/java/java-get-example/java-get-user-input.shtml
Try this
import java.io.*;
BufferedReader reader = new BufferedReader(System.in);
String input = reader.readLine();
What could be wrong:
method getInput is not implemented in Main class
getInput is not static, so main doesn't see it (you could change getInput to static method)
getInput doesn't have String signature, so it doesn't take String as parameter
You've probably figured this out by now, but like everyone else has said, it looks like getInput hasn't been implemented. Meaning you haven't told the program what getInput actually does. You'll need an import, and to add the getInput method something like the following:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
String s1=getInput("Enter First Number") ;
String s2=getInput("Enter second Number");
double d1=Double.parseDouble(s1);
double d2=Double.parseDouble(s2);
double result=d1+d2 ;
System.out.println(result);
}
private static String getInput(String output)
{
Scanner input = new Scanner(System.in);
System.out.println(output);
return input.next();
}
}
The getInput method here takes that string you send it and calls it 'output.' so output = "Enter First Numer" the first time you call it.
Then you create a Scanner object named 'input', which will allow you to read what the user types in the keyboard.
Scanner input = new Scanner(System.in);
Then you send that output message to the user:
System.out.println(output);
Finally, you return the String that was typed by the user, using your input object that will read the next thing the user types. The user will have to hit enter after typing.
return input.next();
If you have any questions about what's happening there let me know.