How to handle cases where allocated object is never used - java

In some cases, the constructor call is everything needed, and I do not need any method invocation on the created object. Depending on Java-Compiler-Preferences, Eclipse gives a warning/error "The allocated object is never used" if I do not assign the created object to a variable, or a warning/error "The value of the local variable is not used" if I assign it to a variable.
I know that I can turn off the warnings/errors in the Eclipse Preferences. My question is: For which reason does Eclipse report "The allocated object is never used"? And if there are good reasons, how should I handle these cases, where no method invocation on the created object is needed?

If all your class's logic is executed in the constructor, perhaps you should move it to a static method instead of creating an instance you'll never use.
A constructor is meant to create an instance of a class to be used later. I think you might be misusing the constructor.

From Eclipse specs this,
When enabled, the compiler will issue an error or a warning when it encounters an allocated object which is not used, e.g.
if (name == null)
new IllegalArgumentException();
But it reports as a bug. Just ignore it no need.

Related

Why don't we need to initialise instance variables [duplicate]

Consider the following code snippet in Java. It won't compile.
package temppkg;
final public class Main
{
private String x;
private int y;
private void show()
{
String z;
int a;
System.out.println(x.toString()); // Causes a NullPointerException but doesn't issue a compiler error.
System.out.println(y); // Works fine displaying its default value which is zero.
System.out.println(z.toString()); // Causes a compile-time error - variable z might not have been initialized.
System.out.println(a); // Causes a compile-time error - variable a might not have been initialized.
}
public static void main(String []args)
{
new Main().show();
}
}
Why do the class members (x and y) declared in the above code snippet not issue any compile-time error even though they are not explicitly initialized and only local variables are required to be initialized?
When in doubt, check the Java Language Specification (JLS).
In the introduction you'll find:
Chapter 16 describes the precise way in which the language ensures
that local variables are definitely set before use. While all other
variables are automatically initialized to a default value, the Java
programming language does not automatically initialize local variables
in order to avoid masking programming errors.
The first paragraph of chapter 16 states,
Each local variable and every blank final field must have a definitely
assigned value when any access of its value occurs....A Java compiler
must carry out a specific conservative flow analysis to make sure
that, for every access of a local variable or blank final field f, f
is definitely assigned before the access; otherwise a compile-time
error must occur.
The default values themselves are in section 4.12.5. The section opens with:
Each class variable, instance variable, or array component is
initialized with a default value when it is created.
...and then goes on to list all the default values.
The JLS is really not that hard to understand and I've found myself using it more and more to understand why Java does what it does...after all, it's the Java bible!
Why would they issue a compile warning?, as instance variables String will get a default value of null, and int will get a default value of 0.
The compiler has no way to know that x.toString(), will cause a runtime exception, because the value of null is not actually set till after runtime.
In general the compiler couldn't know for sure if a class member has or has not been initialized before. For example, you could have a setter method that sets the value for a class member, and another method which accesses that member. The compiler can't issue a warning when accessing that variable because it can't know whether the setter has been called before or not.
I agree that in this case (the member is private and there is no single method that writes the variable) it seems it could raise a warning from the compiler. Well, in fact you are still not sure that the variable has not been initialized since it could have been accessed via reflexion.
Thins are much easier with local variables, since they can't be accessed from outside the method, nor even via reflexion (afaik, please correct me if wrong), so the compiler can be a bit more helpful and warn us of uninitialized variables.
I hope this answer helps you :)
Class members could have been initialized elsewhere in your code, so the compiler can't see if they were initialized at compilation time.
Member variables are automatically initialized to their default values when you construct (instantiate) an object. That holds true even when you have manually initialized them, they will be initialized to default values first and then to the values you supplied.
This is a little little lengthy article but it explains it: Object initialization in Java
Whereas for the local variables (ones that are declared inside a method) are not initialized automatically, which means you have to do it manually, even if you want them to have their default values.
You can see what the default values are for variables with different data types here.
The default value for the reference type variables is null. That's why it's throwing NullPointerException on the following:
System.out.println(x.toString()); // Causes a NullPointerException but doesn't issue a compiler error.
In the following case, the compiler is smart enough to know that the variable is not initialized yet (because it's local and you haven't initialized it), that's why compilation issue:
System.out.println(z.toString()); // "Cuases a compile-time error - variable z might not have been initialized.

Calling constructor from another constructor and illegal argument exception

for my two parameter constructor to call the four parameter constructor is it proper with what I have done(I am still learning). Also it is supposed to instantiate open interval so is that still correct? for the copy constructor how would I make a copy of the explicit value constructor? Also how do I throw an exception if memory has not been allocated for object being copied?
for the copy constructor how would I make a copy of the explicit value constructor?
There is no built-in in Java for this. You'd have to manually copy the fields you want to copy
public LetsCallThisClassInterval(LetsCallThisClassInterval other){
this(other.left, other.right, other.stuff)
}
But this class looks like it should be immutable, so there is no real need for a copy constructor.
Also how do I throw an exception if memory has not been allocated for object being copied?
That just does not happen in Java. Memory is managed for you, and if you get an object reference, it will have been properly allocated already.
Or are you talking about other being null in the above example?
In that case, you will get a NullPointerException automatically. If you prefer an IllegalArgumentException (debatable), you can add a null check:
if (other == null)
throw new IllegalArgumentException("other interval cannot be null");
Let me see if I get this right, you want to do a constructor inception? In this case what you would want to do is use the Constructor(//insert the variables that correspond); that should fix the problem.
Using "this" will make the constructor refer to itself, I mean the same method. For example it would be.
public Constructor(char leftsym, double left, double right, char rightsymb){
new Constructor(left, right);
}
Now as a side note, the Constructor class already exists between the core classes in Java, I suggest that if you want to simplify your life change your java class name such as Constructor_1 or something like that.
Good Luck

What properties are guaranteed by constructors in Java?

I used to think that, intuitively speaking, a constructor in Java is the thing that makes an object, and that nothing can touch that object until its constructor returns. However, I have been proven wrong about this over and over again:
uninitialized objects can be leaked by sharing this
uninitialized objects can be leaked by a subclass accessing it from the finalizer
uninitialized objects can be leaked to another thread before they're fully constructed
All of these facts violate my intuition of what I thought a constructor is.
I can no longer with confidence say what a constructor actually does in Java, or what it's meant to be used for. If I'm making a simple DTO with all final fields, then I can understand what the use of the constructor is, because this is exactly the same as a struct in C except it can't be modified. Other than that, I have no clue what constructors can be reliably used for in Java. Are they just a convention/syntactic sugar? (i.e If there were only factories that initialize objects for you, you would only have X x = new X(), then modify each field in x to make them have non default values - given the 3 facts above, this would be almost equivalent to how Java actually is)
I can name two properties that are actually guaranteed by constructors: If I do X x = new X(), then I know that x is an instance of X but not a subclass of X, and its final fields are fully initialized. You might be tempted to say that you know that constructor of X finished and you have a valid object, but this is untrue if you pass X to another thread - the other thread may see the uninitialized version (i.e what you just said is no different than the guarantees of calling a factory). What other properties do constructors actually guarantee?
All of these facts violate my intuition of what I thought a constructor is.
They shouldn't. A constructor does exactly what you think it does.
1: uninitialized objects can be leaked by sharing this
3: uninitialized objects can be leaked to another thread before they're fully constructed
The problem with the leaking of this, starting threads in the constructor, and storing a newly constructed object where multiple threads access it without synchronization are all problems around the reordering of the initialization of non-final (and non-volatile) fields. But the initialization code is still done by the constructor. The thread that constructed the object sees the object fully. This is about when those changes are visible in other threads which is not guaranteed by the language definition.
You might be tempted to say that you know that constructor of X finished and you have a valid object, but this is untrue if you pass X to another thread - the other thread may see the uninitialized version (i.e what you just said is no different than the guarantees of calling a factory).
This is correct. It is also correct that if you have an unsynchronized object and you mutate it in one thread, other threads may or may not see the mutation. That's the nature of threaded programming. Even constructors are not safe from the need to synchronize objects properly.
2: uninitialized objects can be leaked by a subclass accessing it from the finalizer
This document is talking about finalizers and improperly being able to access an object after it has been garbage collected. By hacking subclasses and finalizers you can generate an object that is not properly constructed but it is a major hack to do so. For me this does not somehow challenge what a constructor does. Instead it demonstrates the complexity of the modern, mature, JVM. The document also shows how you can write your code to work around this hack.
What properties are guaranteed by constructors in Java?
According to the definition, a constructor:
Allocates space for the object.
Sets all the instance variables in the object to their default values. This includes the instance variables in the object's superclasses.
Assigns the parameter variables for the object.
Processes any explicit or implicit constructor invocation (a call to this() or super() in the constructor).
Initializes variables in the class.
Executes the rest of the constructor.
In terms of your 3 issues, #1 and #3 are, again, about when the initialization of non-final and non-volatile fields are seen by threads other than the one that constructed the object. This visibility without synchronization is not guaranteed.
The #2 issue shows a mechanism where if an exception is thrown while executing the constructor, you can override the finalize method to obtain and improperly constructed object. Constructor points 1-5 have occurred. With the hack you can bypass a portion of 6. I guess it is in the eye of the beholder if this challenges the identity of the constructor.
From the JLS section 12.5:
12.5. Creation of New Class Instances
Just before a reference to the newly created object is returned as the
result, the indicated constructor is processed to initialize the new
object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (ยง8.8.7.1) of another constructor in the same class (using this), then
evaluate the arguments and process that constructor invocation
recursively using these same five steps. If that constructor
invocation completes abruptly, then this procedure completes abruptly
for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If
this constructor is for a class other than Object, then this
constructor will begin with an explicit or implicit invocation of a
superclass constructor (using super). Evaluate the arguments and
process that superclass constructor invocation recursively using these
same five steps. If that constructor invocation completes abruptly,
then this procedure completes abruptly for the same reason. Otherwise,
continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable
initializers to the corresponding instance variables, in the
left-to-right order in which they appear textually in the source code
for the class. If execution of any of these initializers results in an
exception, then no further initializers are processed and this
procedure completes abruptly with that same exception. Otherwise,
continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly
for the same reason. Otherwise, this procedure completes normally.
**
Unlike C++, the Java programming language does not specify altered rules for method >dispatch during the creation of a new class instance. If methods are invoked that are >overridden in subclasses in the object being initialized, then these overriding methods >are used, even before the new object is completely initialized.
And from JLS 16.9:
Note that there are no rules that would allow us to conclude that V is
definitely unassigned before an instance variable initializer. We can
informally conclude that V is not definitely unassigned before any
instance variable initializer of C, but there is no need for such a
rule to be stated explicitly.
Happens before 17.4.5:
Threading 17.5.2:
A read of a final field of an object within the thread that constructs
that object is ordered with respect to the initialization of that
field within the constructor by the usual happens-before rules. If the
read occurs after the field is set in the constructor, it sees the
value the final field is assigned, otherwise it sees the default
value.
A class contains constructors that are invoked to create objects from the class blueprint.
This is what Oracle says about constructors.
Now to your point.
intuitively speaking, a constructor in Java is the thing that makes an object, and that nothing can touch that object until its constructor returns.
So according to the official documentation, your assumption is not right. And the point 1 and 2 are the abuse of the rules and behaviors of Java, unless you consciously want to leak your objects! As also being irrelevant to Constructor, I will skip discussing these points.
Now if we talk about your 3rd point, in multi-threaded environment there is nothing that can guarantee you about the consistency of your code, unless "properly synchronized blocks" or "the atomic instructions". As object creation is not a synchronized nor an atomic instruction, there is no guarantee of being consistent! There is nothing the Constructor can do with it. In other words its not the responsibility of the Constructor to make your object creation atomic.
Now, the answer to your question, "What other properties do constructors actually guarantee?" is somewhat easy. Constructors are merely nothing but special type of methods, that are invoked during object creation from the blue print of the class. So it can guarantee nothing, unless you give it a chance to be executed consistently like any other methods. It after being consistently executed it can guarantee you that, your object is created and initialized as you wanted and instructed in it.
constructors is java are just used to initialize the state of the object created..nothing more.

Declaring local variables as final without initializer and assigning in if-statement

I just made a small code change to silence a FindBugs warning which required moving some code to an anonymous inner class. In order to access some variables, I had to declare those as final. So this is the code snippet after the change:
final File[] libPath; // libPath is final but assignment takes place later
if (libraryPath != null) {
libPath = pathToFiles(libraryPath);
} else {
libPath = new File[0];
}
This compiles just fine with language set to Java 6 in current Eclipse (Version 3.7.1). However I'm quite sure this used to give an error in some previous version. Seems the compiler accepts this construct when it can determine that there will be.
My question is: is this legal in Java 6 or is it something that now works due to a side effect of Java 7 support being added to eclipse 3.7.1? We have seen such side effects with certain usage of generics that works in 3.7.1 but didn't compile in 3.7.0.
this is ok. it is called blank final
quote from wiki:
A final variable can only be initialized once, either via an
initializer or an assignment statement. It need not be initialized at
the point of declaration: this is called a "blank final" variable. A
blank final instance variable of a class must be definitely assigned
at the end of every constructor of the class in which it is declared;
similarly, a blank final static variable must be definitely assigned
in a static initializer of the class in which it is declared:
otherwise, a compile-time error occurs in both cases. [4] (Note: If
the variable is a reference, this means that the variable cannot be
re-bound to reference another object. But the object that it
references is still mutable, if it was originally mutable.)
Blank final
The blank final, which was introduced in Java 1.1, is a final variable
whose declaration lacks an initializer. [5][6] A blank final can only
be assigned once and must be unassigned when an assignment occurs. In
order to do this, a Java compiler runs a flow analysis to ensure that,
for every assignment to a blank final variable, the variable is
definitely unassigned before the assignment; otherwise a compile-time
error occurs.[7]
In general, a Java compiler will ensure that the blank final is not
used until it is assigned a value and that once assigned a value, the
now final variable cannot be reassigned another value.[8]
link: http://en.wikipedia.org/wiki/Final_%28Java%29
This was allowed and worked fine since Java 1.1 and will not get you in trouble with other compilers or IDEs.
It is standard behaviour in Java and was first formally specified in the Java Language Specification 2nd Edition.
Java Language Specification contains a whole chapter dedicated to this behaviour (Chapter 16
Definite Assignment).
This behaviour is thoroughly defined, so that I think you misinterpret something when you say that used to produce an error in previous versions.
It's fine. The variable does not have a value, and is assigned only once. It would fail if you have given it a null value initially.
I'd strongly suggest to use this code instead:
final File[] libPath = ibraryPath == null ? new File[0] : pathToFiles(libraryPath);
This does not depend on any compiler version, but is 100% supported Java with a clear meaning.
Yes, this will work and is safe to use in all java versions I've seen (1.3+).
final means that you cannot change the value of the object once it has been initialized, if you placed a null upon declaration it would've broke.

Uninitialized variables and members in Java

Consider this:
public class TestClass {
private String a;
private String b;
public TestClass()
{
a = "initialized";
}
public void doSomething()
{
String c;
a.notify(); // This is fine
b.notify(); // This is fine - but will end in an exception
c.notify(); // "Local variable c may not have been initialised"
}
}
I don't get it. "b" is never initialized but will give the same run-time error as "c", which is a compile-time error. Why the difference between local variables and members?
Edit: making the members private was my initial intention, and the question still stands...
The language defines it this way.
Instance variables of object type default to being initialized to null.
Local variables of object type are not initialized by default and it's a compile time error to access an undefined variable.
See section 4.12.5 for SE7 (same section still as of SE14)
http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5
Here's the deal. When you call
TestClass tc = new TestClass();
the new command performs four important tasks:
Allocates memory on the heap for the new object.
Initiates the class fields to their default values (numerics to 0, boolean to false, objects to null).
Calls the constructor (which may re-initiate the fields, or may not).
Returns a reference to the new object.
So your fields 'a' and 'b' are both initiated to null, and 'a' is re-initiated in the constructor. This process is not relevant for method calling, so local variable 'c' is never initialized.
For the gravely insomniac, read this.
The rules for definite assignment are quite difficult (read chapter 16 of JLS 3rd Ed). It's not practical to enforce definite assignment on fields. As it stands, it's even possible to observe final fields before they are initialised.
The compiler can figure out that c will never be set. The b variable could be set by someone else after the constructor is called, but before doSomething(). Make b private and the compiler may be able to help.
The compiler can tell from the code for doSomething() that c is declared there and never initialized. Because it is local, there is no possibility that it is initialized elsewhere.
It can't tell when or where you are going to call doSomething(). b is a public member. It is entirely possible that you would initialize it in other code before calling the method.
Member-variables are initialized to null or to their default primitive values, if they are primitives.
Local variables are UNDEFINED and are not initialized and you are responsible for setting the initial value. The compiler prevents you from using them.
Therefore, b is initialized when the class TestClass is instantiated while c is undefined.
Note: null is different from undefined.
You've actually identified one of the bigger holes in Java's system of generally attempting to find errors at edit/compile time rather than run time because--as the accepted answer said--it's difficult to tell if b is initialized or not.
There are a few patterns to work around this flaw. First is "Final by default". If your members were final, you would have to fill them in with the constructor--and it would use path-analysis to ensure that every possible path fills in the finals (You could still assign it "Null" which would defeat the purpose but at least you would be forced to recognize that you were doing it intentionally).
A second approach is strict null checking. You can turn it on in eclipse settings either by project or in default properties. I believe it would force you to null-check your b.notify() before you call it. This can quickly get out of hand so it tends to go with a set of annotations to make things simpler:
The annotations might have different names but in concept once you turn on strict null checking and the annotations the types of variables are "nullable" and "NotNull". If you try to place a Nullable into a not-null variable you must check it for null first. Parameters and return types are also annotated so you don't have to check for null every single time you assign to a not-null variable.
There is also a "NotNullByDefault" package level annotation that will make the editor assume that no variable can ever have a null value unless you tag it Nullable.
These annotations mostly apply at the editor level--You can turn them on within eclipse and probably other editors--which is why they aren't necessarily standardized. (At least last time I check, Java 8 might have some annotations I haven't found yet)

Categories