Unnecessary #SuppressWarnings("unused") - java

I'm getting a compiler warning for the #SuppressWarnings annotation in eclipse for the code:
#Override
public boolean doSomething(#SuppressWarnings("unused") String whatever) throws AnException {
throw new AnException("I'm still in bed and can't do anything until I've had a shower!");
}
It looks like a yellow squiggle under the word "unused" and on mouse hover I get the tooltip Unnecessary #SuppressWarnings("unused").
I think another developer is being prompted to put in these annotations by eclipse and I'm basically being prompted to take them out. How can I configure eclipse to prompt me to put the #SuppressWarnings annotation in instead of it complaining about it?
If anyone would like to comment on best practice here then that would also be most welcome.

In the code in your question, the #SuppressWarnings("unused") annotation is unnecessary because the method is either overriding another method from a superclass or implementing an interface. Even if you don't actually use the whatever parameter it's mandatory to declare it, otherwise the #Override annotation will produce an error (you'd be changing the signature of the overridden method if you removed the parameter.)
In some older versions of Eclipse the code as shown would not cause a warning, but in more recent releases it does. I believe it's a valid warning, and I'd rather remove the #SuppressWarnings("unused") in this case.

Go to
Window → Preferences → Java → Compiler → Errors/Warnings → Annotations.
And select Ignore for Unused '#SuppressWarnings` token.

Alternatively, if you think it's more correct to delete the SuppressWarnings annotation:
Window -> Preferences -> Java -> Compiler -> Errors/Warnings -> Unnecessary code -> Value of parameter is not used
and select Ignore in overriding and implementing methods

In my code there's no inheritance defining the 3 methods with #SuppressWarnings("unused")
This code gives 'Unnecessary #SuppressWarnings("unused")' in Eclipse Juno (latest version), but if I remove the #SuppressWarnings("unused"), I get "Constructor/Method is never used" warnings in IntelliJ IDEA 11.1.3
The methods aren't directly used in the project, only by 3rd party products Jackson, JAXB & GSON, so IntelliJ is right, I would say ...
public class EmailUnsendable extends SkjemaError {
private NestedCommand command; // Can't be Command (interface) because of GSON!
#SuppressWarnings("unused") // Used by Jackson/JAXB/GSON
public EmailUnsendable() {
}
public EmailUnsendable(String referenceNumber, String stackTrace, NestedCommand command) {
super(referenceNumber, stackTrace);
this.command = command;
}
#SuppressWarnings("unused") // Used by Jackson/JAXB/GSON
public NestedCommand getCommand() {
return command;
}
#SuppressWarnings("unused") // Used by Jackson/JAXB/GSON
public void setCommand(NestedCommand command) {
this.command = command;
}
}
I believe this is an error in Eclipse.

Related

How to disable "unnecessary test for null" warning in NetBeans 14?

Short Version
How do i disable the "unnecessary test for null" warning in NetBeans 14 IDE?
Long Version
NetBeans as a well-known bug 1 2 3 4 where it will erroneously tell you that a test for null is unnecessary. For example in the following code:
import javax.validation.constraints.NotNull;
private void doSomething(#NotNull Object o) {
if (o == null) return;
//...do more stuff...
}
The IDE thinks
because the o parameter was tagged as #NotNullo
it must be impossible for o to be null
so it must be that the if statement is unnecessary
This is demonstrably false
The #NotNull annotation is only an IDE hint, not a runtime guarantee.
just because an argument to a method is tagged as #NotNullable
does not mean it cannot be null
You can prove this to yourself by passing null to the doSomething method. (we can even write the test code so the IDE generates no hints or warnings at all!):
Object o = getTestValue();
doSomething(o);
private Object getTestValue()
{
Object o = null;
return o;
}
private void doSomething(#NotNull Object o) {
Objects.requireNonNull(value);
//...do more stuff...
}
And watch doSomething method fail - because o is null - even though it is tagged #NotNull.
Now, there may be other implementations of #NotNull, or other compilers that add runtime checks. I'm not talking about those. The NetBeans IDE 14 warning is wrong, so i need to disable it.
Research Effort
I tried clicking the lightbulb, to hopefully configure the warning:
but it only offers to configure null deference warnings - which i definitely want to keep.
I tried pressing Alt+Enter to bring up more options:
but nothing of value appears:
I tried to let it bring me to the area to configure the Null dereferncing hint:
but it definitely has nothing to do with *unnecessary test for null.
I tried searching for a hint or warning named "null":
but it's not there.
I tried searching for a hint or warning named "unnecessary":
but it's not there.
I tried searching for a hint or warning named "test":
but it's not there.
How to turn it off
Which brings me to my question:
given that NetBeans IDE 14 has no way to turn off "unnecessary test for null" warning
how do i turn off the "unnecessary test for null" warning in NetBeans IDE 14?
Bonus Reading
What does unnecessary test for null mean?
Netbeans tells me to remove null comparison, but that breaks my code ("First thing to note is: NetBeans is wrong")
BugZilla: Bug 226923 - Wrong warning 'the expression is never null'
Bugzilla: Bug 262707 - Add configuration of Nullable/NonNull annotations. Use FQNs or allow to exclude FQNs.
You can turn off the "Unnecessary test for null" warning using the Java annotation #SuppressWarnings("null"). That annotation is found in java.lang, and there is no need for an import.
The OpenJDK Javadoc for SuppressWarnings for JDK 17 states:
Indicates that the named compiler warnings should be suppressed in the
annotated element (and in all program elements contained in the
annotated element) ... As a matter of style, programmers should always
use this annotation on the most deeply nested element where it is
effective. If you want to suppress a warning in a particular method,
you should annotate that method rather than its class.
From the linked documentation to section 9.6.4.5 of the Java Language Specification, #SuppressWarnings appears to do exactly what you want, with my emphasis added:
9.6.4.5. #SuppressWarnings
Java compilers are increasingly capable of issuing helpful "lint-like"
warnings. To encourage the use of such warnings, there should be some
way to disable a warning in a part of the program when the programmer
knows that the warning is inappropriate.
Here's sample code, based on that in the OP:
package suppression;
import javax.validation.constraints.NotNull; // Jakarta EE 8
//import jakarta.validation.constraints.NotNull; // Jakarta EE 9
public class Suppression {
public static void main(String[] args) {
Suppression supp = new Suppression();
Object o = supp.getTestValue();
supp.doSomething(o);
supp.doSomething2(o);
}
Object getTestValue() {
Object o = null;
return o;
}
private void doSomething(#NotNull Object o) {
if (o == null) {
System.out.println("Object is null!");
}
}
#SuppressWarnings("null")
private void doSomething2(#NotNull Object o) {
if (o == null) {
System.out.println("Object is null!");
}
}
}
Here's a screenshot of that code in NetBeans 14 which shows:
The unwanted warning "Unnecessary test for null" is shown on line 22 in method doSomething().
The annotation #SuppressWarnings("null") on line 27 prevents the unwanted warning "Unnecessary test for null" being shown on line 30 in the otherwise identical method doSomething2().
The answer is: it cannot be done.
NetBeans provides no way to disable the unnecessary test for null warning.
Workaround
As other people in other answers have noted:
the value can be null
NetBeans is wrong thinking it cannot be null
The correct way to resolve the (incorrect) warning is to obfuscate the check for null.
Rather than calling:
if (customer == null) { ... }
Instead call:
if (Object.isNull(customer)) { ... }
It is the same thing; except this way NetBeans doesn't realize that you're testing the variable for null, and so doesn't warn you.

Missing annotation: #Override is not shown by compiler in Eclipse IDE

This is kind of weird! but when I implement Collection for my modal class and add unimplemented methods using Eclipse IDE, it is not showing #Override in any of the methods which are generated by clicking on "Add Unimplemented Methods".
public class MadeItACollection implements Collection{
}
When I click on "Add Implemented Methods" the following happens:
public class MadeItACollection implements Collection{
public int size() {
// TODO Auto-generated method stub
return 0;
}
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}
.
.
.
.
}
I dont see any #Override. I am compiling my codebase in Java 8. Am I missing something obvious?
As peoples' comments suggest, this is a Code Style option within Eclipse.
You can enable it under Preferences -> Java -> Code Style -- ensure that the "Add #Override annotation for new overriding methods" is checked; after, you can also look into adding it for implementations of interface methods via the link directly underneath. (You can also enable automatic adding of the annotation as a Cleanup or Save action in these menus.)
The #Override annotation isn't strictly required when implementing an interface mainly because you aren't overriding any superclass implementation you are actually implementing the interfaces declared methods. So maybe a #Implements annotation is required, but that's a whole different topic of conversation.
However, it is strongly recommended that you still use the #Override annotation on these methods because:
It explicitly conveys to anybody reading the code that it is an overriding method.
It helps avoid shooting yourself in the foot by throwing a compile time error if you misspell the method you want to override because it will tell you if the method can actually override an existing super method.
Most IDEs actually will help you add this automatically:
Intellij Idea:
Navigate to
File => Settings => Editor => Code Style => Java
And scroll to Override Method Signature and you should find Insert #Override annotation, make sure this is checked.
The Jetbrains documentation says the below about this setting option:
Insert #Override Annotation: Select this checkbox to have IntelliJ IDEA insert #Override annotations automatically.
Eclipse:
Navigate to:
Window => Preferences => Java => Code Style
And look for Add #Override annotation for new overriding methods and make sure it has been checked.
You can also add it as a Save Action by navigating to:
Window => Preferences => Java => Editor => Save Actions
And ensuring that Perform the selected actions on save has been selected and that Additional actions has been selected and ensuring that Add missing Annotations has been configured

AspectJ trouble using around advice and ProceedingJoinPoint

I'm new to AOP and I need to use AspectJ on my project.
I need to use around advice but I have a problem using it, I've the following code in my .aj class,
pointcut checkUser(ProceedingJoinPoint jp,User user): call(* com.example.UserAccount.MyUI.checkUser(..))&& args(jp,user);
void around(ProceedingJoinPoint jp,User user) throws Throwable : checkUser(jp,user){
// Condition checks one of the user boolean property
if(condition){
jp.proceed();
}else{
// Do nothing
}
}
but I get this warning all the time,
advice defined in Aspects.UserAccount has not been applied [Xlint:adviceDidNotMatch]
By the way, I tried it without ProceedingJoinPoint and tried just proceed(); but then got this warning, too few arguments to proceed, expected 1
I'm thankful for any single help or hint!
Reza
First I recommend to read the AspectJ documentation in order to learn the syntax. As you are using native AspectJ syntax, this is like learning a new programming language or at least a Java extension. What you are doing is mix native syntax with annotation-based syntax. Try to stick with one. I am sure that you did not find this in any tutorial but ended up with that syntax via trial and error.
You do not need to bind a joinpoint parameter in native syntax because it is there implicitly and automatically. The automatically bound joinpoint is always named thisJoinPoint as all tutorials surely show you. Only in annotation-based syntax you need to bind the joinpoint and can name it as you wish, but even then I recommend to stick with thisJoinPoint because then refactoring from annotation to native syntax is easier and your eyes get used to spotting that variable name in your aspect code.
The warning you get means that the pointcut you defined does not match any part of your code, at least not any part which is visible to the aspect weaver or compiler. There could be plenty of reasons why this can occur, e.g. misspelled package or class names, wrong around advice return type (return type must be Object for non-void methods or more specifically match what the method you want to intercept returns). Assuming that e.g. checkUser(..) returns a boolean, the around advice should do the same. I made up an example using your package and class names. Besides, package names should be lower-case but I used yours, assuming they are really package names and not inner classes:
Helper class:
package com.example.UserAccount;
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return "User(" + name + ")";
}
}
Class targeted by aspect + sample main method:
package com.example.UserAccount;
public class MyUI {
public boolean checkUser(User user) {
return user.getName().toUpperCase().contains("ADMIN");
}
public static void main(String[] args) {
MyUI ui = new MyUI();
System.out.println(ui.checkUser(new User("Administrator")));
System.out.println(ui.checkUser(new User("john")));
System.out.println(ui.checkUser(new User("xander")));
System.out.println(ui.checkUser(new User("admiral")));
System.out.println(ui.checkUser(new User("SySaDmiN")));
}
}
As you can see, we expect an output of "true" for the first and last entry, but "false" for the ones in between due to the check logic I made up for checkUser(..).
Now let us write an aspect which also returns "true" for a user named "Xander", e.g. in order to give him admin rights or whatever. I am making this up because you did not provide an MCVE as you always should on StackOverflow, but just an incoherent code snippet which keeps everyone trying to answer your question guessing what the heck you might want to achieve and how to reproduce your problem.
Aspect:
package Aspects;
import com.example.UserAccount.User;
import com.example.UserAccount.MyUI;
public aspect UserAccount {
pointcut checkUser(User user) :
execution(boolean MyUI.checkUser(*)) && args(user);
boolean around(User user) : checkUser(user) {
System.out.println(thisJoinPoint + " -> " + user);
if (user.getName().equalsIgnoreCase("xander"))
return true;
return proceed(user);
}
}
I just imported the MyUI class, so there is no need to use a fully-qualified class name here. Again, this is an advantage of native syntax, in annotation-based syntax you would have to use the fully qualified name.
I also replaced the generic * MyUI.checkUser(..) (which would also work) by the more explicit boolean MyUI.checkUser(*) because we already know that the method returns a boolean and has exactly one parameter, which both we assume anyway by returning a boolean from the around advice and by binding exactly one parameter via args(). You could also be even more specific and use boolean MyUI.checkUser(User).
Furthermore, I am using execution() rather than call() because it is more efficient, as it weaves the advice code just into the executing method once instead of five times for each method call in the main method. You only need to use call() if the MyUI class is out of reach of the AspectJ weaver/compiler, i.e. because it is not in the module you compile with AspectJ Maven.
Console log:
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(Administrator)
true
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(john)
false
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(xander)
true
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(admiral)
false
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(SySaDmiN)
true
Et voilà, the aspect works. It makes the target method return "true" for user "xander".

Android annotation processing - generate different code for different build flavor

I'm building a library that requires some annotation processing to generate code. I now run into an issue that the release build doesn't need to have as much code as the debug build does (since this is a library for modifying configuration variants - primarily used for testing purposes). The following code illustrates the situations. Let's say I want to create a class ConfigManager from some annotated classes and properties. In debug builds, I need this much:
public class ConfigManager {
public Class getConfigClass() {
return abc.class;
}
public void method1() {
doSomething1();
}
public void method2() {
doSomething2();
}
public void method3() {
doSomething3();
}
}
While in release builds, I only need this much:
public class ConfigManager {
public Class getConfigClass() {
return abc.class;
}
}
I have a feeling it may be possible by writing a Gradle plugin to check for build flavor at compile time and invoke a different processor/or somehow pass a parameter to a processor to generate different code. However this topic is pretty new to me so I'm not sure how to achieve this. A couple hours of googling also didnt help. So I'm wondering if anyone could give me a direction or example? Thanks
Pass an option (release=true/false) to your processor.
From javac https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html
-Akey[=value]
Specifies options to pass to annotation processors. These options are not interpreted by javac directly, but are made available for use by individual processors. The key value should be one or more identifiers separated by a dot (.).
In combination with Processor.html#getSupportedOptions https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html#getSupportedOptions
Returns the options recognized by this processor. An implementation of the processing tool must provide a way to pass processor-specific options distinctly from options passed to the tool itself, see getOptions.
Implementation outline:
public Set<String> getSupportedOptions() {
Set<String> set = new HashSet<>();
set.add("release");
return set;
}
// -Arelease=true
boolean isRelease(ProcessingEnvironment env) {
return Boolean.parseBoolean(env.getOptions().get("release"));
}
See Pass options to JPAAnnotationProcessor from Gradle for how to pass options in a gradle build.

Unclear inspection warning "NullableProblems" in IntelliJ

Why am I getting a warning from the "NullableProblems" inspection in IntelliJ on this:
public class Test implements Comparable<Test> {
#Override
public int compareTo(Test o) {
return 0;
}
}
I'm using IntelliJ 14.1.4 and compiling with Java 1.7
Screenshot:
Adding #NotNull before the argument doesn't help:
From Comparable.compareTo:
#throws NullPointerException if the specified object is null
So IntelliJ knows, that the object should not be null and adds a #NotNull annotation automatically:
IntelliJ IDEA will look carefully at SDK and libraries bytecode and will infer these annotations automatically so that they can later be used to analyze source code to spot places where you overlooked null.
Your overriden method doesn't include this annotation, so it overrides this behavior making the parameter nullable - against the contract of the Comparable interface.
You can solve this by adding #NotNull before the parameter.
You can also disable this inspection by pressing Alt + Enter, selecting the warning in the popup menu and selecting Disable inspection in the sub-menu.
Check out the Web Help and this thread for more information about #NotNull / #NonNull annotations.
This can be globally configured in IntelliJ IDEA easily and for me personally is the recommended way. If you want you can add your own annotations.
i.e. javax.validation.constraints.NotNull
Path to the setting:
Settings > Editor > Inspections > #NotNull/#Nullable problems > Configure annotations
Some screenshots:
Its because that you are overriding a method that does not have a #NotNull annotation.
IntelliJ IDEA warns you if the overriding method does not have a #NotNull annotation.

Categories

Resources