Constant variable might already have been assigned - java

I really need help. Don't know how to fix this. I wanna load some constants from properties file. I think, that Catch with FileNotFoundException can be thrown only on the properties.load(). But IDE says that
VK_MIN_ID = VK_MIN_ID_DEFAULT;
VK_MAX_ID = VK_MAX_ID_DEFAULT;
MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
this variables might already have been assigned. Where?
Full code:
private static final int VK_MIN_ID;
private static final int VK_MIN_ID_DEFAULT = 1;
private static final int VK_MAX_ID;
private static final int VK_MAX_ID_DEFAULT = 999_999_999;
private static final int MAX_USERS_TO_PARSE_AT_ONCE;
private static final int MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT = 500;
static {
FileInputStream fileInputStream;
Properties properties = new Properties();
try {
fileInputStream = new FileInputStream("src/main/resources/vk.properties");
properties.load(fileInputStream);
if (properties.containsKey("vk.min.id")) {
VK_MIN_ID = Integer.parseInt(properties.getProperty("vk.min.id"));
} else {
VK_MIN_ID = VK_MIN_ID_DEFAULT;
}
if (properties.containsKey("vk.max.id")) {
VK_MAX_ID = Integer.parseInt(properties.getProperty("vk.max.id"));
} else {
VK_MAX_ID = VK_MAX_ID_DEFAULT;
}
if (properties.containsKey("max.users.to.parse.at.once")) {
MAX_USERS_TO_PARSE_AT_ONCE = Integer.parseInt(properties.getProperty("max.users.to.parse.at.once"));
} else {
MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
}
} catch (FileNotFoundException e) {
logger.warn("Файл свойств отсуствует! Устанавливаем настройки по умолчанию...");
VK_MIN_ID = VK_MIN_ID_DEFAULT;
VK_MAX_ID = VK_MAX_ID_DEFAULT;
MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
} catch (IOException e) {
logger.error("Ошибка чтения файла свойств! Работа будет прекращена", e);
}
}
Big thanks.

The Java compiler doesn't see what we can see -- that the assignment to MAX_USERS_TO_PARSE_AT_ONCE is at the end of the try block, so that either it gets assigned there or in the catch block. It sees a possibility that it gets assigned in the try block, an exception is thrown, and it gets assigned again in the catch block.
Use a temporary variable to work around this.
int temp;
try {
// other code
if (properties.containsKey("max.users.to.parse.at.once")) {
temp = Integer.parseInt(properties.getProperty("max.users.to.parse.at.once"));
} else {
temp = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
}
} catch (FileNotFoundException e) {
// other code.
temp = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
} catch (IOException e) {
// You'll need to assign something to temp here too.
}
After the last catch block, then assign temp to your final variable, once.
MAX_USERS_TO_PARSE_AT_ONCE = temp;
This way you can keep MAX_USERS_TO_PARSE_AT_ONCE final.

Instead of having a try-catch, and having values set in the catch block, you can replace all that with a simple if-else, and that will work without having to remove the final. Something like this:
File f = new File("src/main/resources/vk.properties");
if (f.exists()) {
// set values here from FileInputStream
// ...
} else {
// set alternate values here if the file is not found.
VK_MIN_ID = VK_MIN_ID_DEFAULT;
VK_MAX_ID = VK_MAX_ID_DEFAULT;
MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
}
EDIT
The reason why you can't assign the constants from the catch block, is because, even though you know that the exception will be caught before the values are set for the first time, the compiler doesn't know that for a fact. It has to assume that the exception can be thrown anywhere in the try block. And so, from the perspective of the compiler, it is possible for the final variables to have been set before the exception is caught, so it gives you the error.

The problem is this:
VK_MIN_ID = VK_MIN_ID_DEFAULT;
VK_MAX_ID = VK_MAX_ID_DEFAULT;
MAX_USERS_TO_PARSE_AT_ONCE = MAX_USERS_TO_PARSE_AT_ONCE_DEFAULT;
VK_MIN_ID, VK_MAX_ID and MAX_USERS_TO_PARSE_AT_ONCE are declared as final, this means that once assigned you can't change their value. Remove final keyword.

Related

Ho to fix error "not able to initialize final variable in static block"?

I have an error where I can "Not able to initialize final variable "classpath" in static block"
class A {
static final String classPath;
static {
try {
classPath = new ClassPathResource("").getFile().toString();
} catch (IOException e) {
e.printStackTrace();
}
}
}
How can I circumvent or untie it? Thx
The problem is that you're not assigning the variable in the exception case.
Assuming that you actually need the value of classPath to be correct, you may as well throw an exception, to indicate that something has gone terminally wrong, and this class cannot be used:
static {
try {
classPath = ...
} catch (IOException e) {
throw new RuntimeException(e);
}
}
(And if you don't actually need it, remove the field!)
Whilst it doesn't make sense to set a default value, it's instructive to look at why you can't set one in the catch block.
try {
classPath = ...
} catch (IOException e) {
classPath = defaultValue; // classPath may already be assigned.
}
This is because of the rules of definite assignment for try statements:
V is definitely unassigned before a catch block iff all of the following are true:
V is definitely unassigned after the try block.
...
So, without looking at the other things which must be true, V is not definitely unassigned after the try block (i.e. if the assignment succeeds), so it is not definitely unassigned in the catch block; as such, you can't assign another value.
Note that if you want to assign a default value, you would need to either assign a local variable first:
String classPath;
try {
classPath = ...
} catch (IOException e) {
classPath = defaultValue;
}
A.classPath = classPath;
Or define a static method:
class A {
static final String classPath = getClassPath();
static String getClassPath() {
try {
return ...;
} catch (IOException e) {
return defaultValue;
}
}
}
(The advantage of the latter being that you can invoke it in unit tests; the disadvantage is that it breaks checking that any static variables used in the method (or other methods called) are actually initialized).
The logic is correct, but you need to initialize the value not matter what. Here, in case of an exception, you don't do it.
You need to manage the case where you have an exception :
Default value ( a valid is better ! )
Of course, you can't just write two statement that would instantiate it, you can use a local variable
String s;
try{
s = new ClassPathResource("").getFile().toString();
} catch (IOException e){
s = MyDefaultValue;
}
classPath = s;
Or let a static method to do it for you (to much logic in a static block is messy)
throw a RuntimeException, this will be valid and will stop the execution. (Thanks #Andy Turner and his example)
class A {
private static final String classPath;
static {
String tempPath=null;
try {
tempPath=new ClassPathResource("").getFile().toString();
} catch (IOException e) {
e.printStackTrace();
}
classPath=tempPath;
}
}
It will work.

variable not defined in java try catch return statement

It is showing temp_lib is not declared, but it is already declared.
Library temp_lib is already declared after try and return, temp_lib is written at last but also it is asking for me to initialize the variables.
int numAdded=0;
File inputfile;
inputfile = new File("export_Library.txt");
try {
Library temp_lib;
Scanner inputScanner = new Scanner(inputfile);
System.out.println("processing a library...");
String name=inputScanner.nextLine();
int capacity=Integer.parseInt(inputScanner.next());
temp_lib=new Library(name,capacity);
LibraryItem item=new LibraryItem();
while(inputScanner.hasNextLine()){
item.setTitle(inputScanner.nextLine());
item.setID_code(inputScanner.nextLine());
item.setYearOfPublication(Integer.parseInt(inputScanner.nextLine()));
if(inputScanner.next()=="1")
{
item.setOnLoan(true);
}
else
{
item.setOnLoan(false);
}
item.setReplacementCost(inputScanner.nextDouble());
}
inputScanner.close();
}
catch (IOException e) {
System.out.println("IO Exception reading shapes from file"+e);
e.printStackTrace() ;
//return temp_lib;
}
return temp_lib;
Library temp_lib; must be before the try-catch block in order to be in scope after the try-catch block.
Library temp_lib = null; // you must give it an initial value, or the code
// won't compile
try {
...
}
catch (..) {
...
}
return temp_lib;

Java: lists, bufferedScanner and Error: java.lang.NullPointerException

I keep getting the error message Error: java.lang.NullPointerException at runtime. Obviously I understand that this shows when I am referencing some variable that has a null value when it should have some value. Thought it best to show you the code so I can put it into context.
public class MarathonAdmin
{
private List<Runner> runners;
/**
* Constructor for objects of class MarathonAdmin
*/
public MarathonAdmin()
{
// initialise instance variables
List<Runner> runners = new ArrayList<>();
}
public void readInRunners()
{
String pathName = OUFileChooser.getFilename();
File aFile = new File(pathName);
Scanner bufferedScanner = null;
try
{
String runnerName;
int runnerAge;
String ageGroup;
Scanner lineScanner;
String currentLine;
bufferedScanner = new Scanner(new BufferedReader(new FileReader(aFile)));
while (bufferedScanner.hasNextLine())
{
currentLine = bufferedScanner.nextLine();
lineScanner = new Scanner(currentLine);
lineScanner.useDelimiter(",");
runnerName = lineScanner.next();
runnerAge = lineScanner.nextInt();
Runner runnerObject = new Runner();
if (runnerAge < 18)
{
ageGroup = "junior";
runnerObject.setAgeGroup(ageGroup);
}
else
if (runnerAge > 54)
{
ageGroup = "senior";
runnerObject.setAgeGroup(ageGroup);
}
else
{
ageGroup = "standard";
runnerObject.setAgeGroup(ageGroup);
}
runnerObject.setName(runnerName);
runners.add(runnerObject);
}
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
finally
{
try
{
bufferedScanner.close();
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
}
}
The test code to create an instance of the class is:
MarathonAdmin ma = new MarathonAdmin();
ma.readInRunners();
There is a class in use called Runners which is already set up with its protocols. The class compiles but the ma.readInRunner(); message ends in an error. The text file that the program is to run from has no errors.
I'm somewhat new to programming and so find it hard to troubleshoot issues. Hopefully someone can help me out.
In the constructor it should be
public MarathonAdmin()
{
// initialise instance variables
this.runners = new ArrayList<>();
}
and not
public MarathonAdmin()
{
// initialise instance variables
List<Runner> runners = new ArrayList<>();
}
The problem is that you have made a Try-catch block, but in the catch part you are not printing the stacktrace, see:
catch (Exception anException)
{
System.out.println("Error: " + anException); // just prints: Error: java.lang.NullPointerException
}
Improve this catch block for debugging, for example like this:
catch (Exception e) {
e.printStackTrace(); //prints the full stacktrace
}
Now you should get a full stacktrace that also shows you the line number and you will be able to debug it yourself ;-)
In fact you probably should remove that try-catch blocks at all.

Unable to add strings into arrayList

may i know why? i have passed in three strings to the addTab method and it is there in the variable when i debug but it says it is null why is that so? i have also instantiated the arrayList
public class STFile implements Serializable{
private ArrayList<String> qnsTitle;
private ArrayList<String> qnsImagePath;
private ArrayList<String> qnsSoundPath;
private Boolean fileExist;
//Constructor for STFile,gets existing data files if exists and load values from it to data files arraylists, if dont exist
//arraylists for data file will be instantiated.
public STFile()
{
setFileExists(checkIfAllFileExist());
if(getFileExist())
{
try {
setQnsTitle(STFile.readFile(STMain.TITLES_PATH));
setQnsImagePath(STFile.readFile(STMain.IMAGES_PATH));
setQnsSoundPath(STFile.readFile(STMain.SOUNDS_PATH));
}catch(IOException e)
{
System.out.println("in class STFile, IOEXception");
}catch(ClassNotFoundException e)
{
System.out.println("in class STFile, ClassNotFoundException");
}
}else
{
File titleFile = new File(STMain.TITLES_PATH);
File imageFile = new File(STMain.IMAGES_PATH);
File soundFile = new File(STMain.SOUNDS_PATH);
qnsTitle = new ArrayList<String>();
qnsImagePath = new ArrayList<String>();
qnsSoundPath= new ArrayList<String>();
}
}
public void addTab(String title,String imagePath,String soundPath)
{
getQnsTitle().add(title);
getQnsImagePath().add(imagePath);
getQnsSoundPath().add(soundPath);
try {
writeFiles();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("in STFile addtab Exception");
e.printStackTrace();
}
}
public static ArrayList<String> readFile(String filePath) throws ClassNotFoundException, IOException
{
ArrayList<String> arraylist = new ArrayList<String>();
ObjectInputStream obj_in = null;
FileInputStream f_in = null;
try {
f_in = new FileInputStream(filePath);
obj_in = new ObjectInputStream (f_in);
arraylist = (ArrayList<String>)obj_in.readObject();
return arraylist;
}catch(Exception e){
return null;
}finally{
f_in.close();
obj_in.close();
return null;
}
}
main method.
STFile file = new STFile();
file.addTab("Title", "image", "sound");
it keeps throwing
Exception in thread "main" java.lang.NullPointerException
at STFile.addTab(STFile.java:53)
at STMain.main(STMain.java:18)
Your readFile method will always return null, because you've got return null; in your finally block.
So if the file exists, qnsTitle (etc) will be null, causing the NullPointerException later.
I would strongly advise you not to catch Exception in the way you're doing in readFile, either. Only catch specific exceptions if you must do so at all - but in this case I wouldn't in the first place, or possibly only to wrap it in a different exception. Simply returning null from the catch block is hiding the fact that something's gone wrong, and introducing another problem further down the line. I suggest you just expand the throws clause of your method (e.g. to include IOException) and remove the catch block.
having return null; in your finally block in readFile could be the problem, try removing that.

Assign final variable in a try block

Very short question: Is there a more elegant way to do this:
Object tmp;
try {
tmp = somethingThatCanFail();
} catch (Fail f) {
tmp = null;
}
final Object myObject = tmp;
// now I have a final myObject, which can be used in anonymous classes
You could extract the creation of the value in its own method:
final Object myObject = getObjectOrNull();
public Object getObjectOrNull() {
try{
return somethingThatCanFail();
} catch (Fail f) {
return null;
}
}
It's longer, but depending on your definition of "elegant" it might be more elegant.
Depends what you mean by "this" (and "more elegant")
I'm not sure why you think you need tmp AND myObject, but there's no way to avoid having one of those declarations outside the try block IF you want to access it in the catch block.
What's wrong with
Object myObject = null;
try {
myObject = somethingThatCanFail();
} catch (Fail f) {
// do nothing because we can deal with myObject being null just fine
}
These days I tend to do it like this
final Thingy zeFing; {
Thingy t = null;
try {
t = somethingThatCanFail();
} catch (CurveBall f) {
// log...
}
zeFing = t;
}

Categories

Resources