Eclipse: contradicting warnings - java

Here's the code snippet:
class MyClass {
private native void foo();
}
For the above, Eclipse (namely, 3.7.0) gives a warning
The method foo() from the type MyClass is never used locally
Alright, but when I try to suppress the warning:
class MyClass {
#SuppressWarnings("unused")
private native void foo();
}
It complains
Unnecesary #SuppressWarnings("unused")
So, is there any way to make it stop complaining?
Update
Sorry for the incomplete information - this warning is only displayed in an AspectJ project. Once I create a simple Java project and put my class in it, all works fine.
As far as I understand, AspectJ uses its own compiler, so this warning must be generated by it. I'm using AspectJ Development Tools plug-in:
Version: 2.1.3.e37x-20110628-1900
AspectJ version: 1.6.12.20110613132200

The list of #SuppressWarnings is compiler specific. In Eclipse,
unused is macro for unusedArgument, unusedImport, unusedLabel, unusedLocal, unusedPrivate and unusedThrown
The whole list is here : the list of valid #SuppressWarnings supported in Eclipse

Inside of a Java project, this produces no warnings:
class MyClass {
private native void foo();
}
This, however, produces a Unnecessary #SuppressWarnings("unused") warning:
class MyClass {
#SuppressWarnings("unused")
private native void foo();
}
Inside of an AspectJ project, the first example produces a The method foo() from the type MyClass is never used locally warning and the second example produces the same warning as in a Java project. This is likely an AspectJ bug. I'd recommend raising an issue on the AspectJ bugzilla.
https://bugs.eclipse.org/bugs/
The AspectJ compiler is a fork of the JDT compiler from Eclipse 3.3. So, it is likely that this bug was originally in Eclipse 3.3. Now that Java 7 is available, AspectJ will likely migrate to being Eclipse 3.7 or 3.8 based and it will pick up the fix from the JDT compiler. But it is worth raising a bug anyway.

I just tried and I don't get the "unnecessary..." warning. Are you sure that the warning is issued by the java compiler and not by some other tool such as checkstyle or findbugs?
Anyway, there are few situations, where an unused private method makes sense.

It's working for me. I'm running Eclipse Indigo like you.

Related

Intellij highlights error but code can be compiled and running correctly

I met a strange issue in Intellij Ultimate 2019.3.2.  It indicates a Java generic type error, like 'reason: no instance(s) of type variable(s) exist so that OCPerson conforms to IBaseObject' when I integrated a jar which provides a generic method in my current project, but the project can be compiled without any error or warning in Oracle JDK 8. More strange, when I use the generic method as source code directly, Intellij doesn't promote the error any more. Please see the detailed information in below:
The generic method signature looks like the below: 
public static <T extends IBaseObject> void setEntityNameForMapObject(Map map, String key, Class<T> entityClass)
I built it  as a single jar library. When I used this jar in a project, Intellij indicated the below error information. Actually, Gradle can compile the project correctly and there is no any warning message. BTW, the Intellij  uses JDK 1.8.0_152. When I copy the source code in the current project, the indicated error message is gone in Intellij. 

Eclipse fails where javac and IDEA succeed

Consider the following self-contained sample:
package bloopers;
import java.lang.annotation.Annotation;
public final class Blooper5
{
interface Converter<T,F>
{
T convert( F from );
}
interface Identifier<T>
{
}
static class ConvertingIdentifier<F,T> implements Identifier<F>
{
ConvertingIdentifier( Converter<T,F> converter )
{
}
}
static final class AnnotationIdentifier
{
Identifier<Annotation> I1 = new ConvertingIdentifier<>(
a -> a.annotationType() );
Identifier<Annotation> I2 = new ConvertingIdentifier<>(
Annotation::annotationType ); //<-- ERROR
Identifier<Annotation> I3 = new ConvertingIdentifier<>(
(Converter<Class<? extends Annotation>,Annotation>)
Annotation::annotationType );
}
}
The code above compiles just fine under the following:
javac from the command line.
IntelliJ IDEA configured to use the javac compiler.
But it fails to compile with the following:
Eclipse
IntelliJ IDEA configured to use the Eclipse compiler.
Eclipse fails to compile the line marked with <-- ERROR, giving the following message:
The constructor Blooper5.ConvertingIdentifier<Annotation,Class<capture#5-of ? extends Annotation>>(Blooper5.Converter<Class<? extends Annotation>,Annotation>) is undefined
Admittedly, this code really pushes the generic parameter type inference capabilities of the compiler, but still, I would like to know precisely what the discrepancy is, no matter how small.
Some exposure of my methods in case someone manages to see something wrong that I fail to see:
The command I used to compile with javac was "c:\Program Files\Java\jdk1.8.0_40\bin\javac" Blooper5.java.
I have version 14.1 of IntelliJ IDEA. Under Project Structure/SDKs I only have "1.8" which points to C:\Program Files\Java\jdk1.8.0_40 and under Project Structure/Modules the specific module is configured to use the "Project SDK (1.8)" which lists as 1.8 (java version "1.8.0_40").
As for Eclipse, I am using Eclipse for RCP and RAP Developers - Version: Luna Release (4.4.0) - Build id: 20140612-0600. Under Preferences/Java/Installed JREs I only have jdk1.8.0_40, and it is the default. Under Execution Environments it is also checked as a "Compatible JRE" of "JavaSE-1.8". And in my Project/Properties/Java Build Path/Libraries the "JRE System Library" is [jdk1.8.0_40].
More noteworthy facts:
It is not just me; it also fails on a colleague's (very similar) eclipse installation.
IntelliJ IDEA says that the lambda expression a -> a.annotationType() can be replaced with a method reference, but if asked to do so, it does not convert it to Annotation::annotationType; instead, it converts it to (Converter<Class<? extends Annotation>, Annotation>) Annotation:: annotationType.
So, the question:
What is causing these discrepancies between Eclipse and the others, and what can be done to eliminate these discrepancies?
(Obviously, the goal is to eliminate the unfortunately too frequently occurring scenario where one developer commits code which fails to compile on another developer's IDE.)
EDIT: When I originally posted this question I thought that IDEA using the Eclipse compiler also compiled fine, but I was wrong. It turns out that it is possible to get IDEA to fail to compile the above code by selecting the Eclipse compiler. Still, the question is why there is a discrepancy between eclipse and javac.
The answer to "why is there a discrepancy" is straightforward but perhaps not very satisfactory: because compilers have bugs and are furthermore open to interpretation of a very complex language specification. Determining whether it's a bug in javac or Eclipse is a difficult task; I've seen such discrepancies end up being declared both ways, sometimes as Eclipse compiler bugs, sometimes as javac bugs. That determination, especially when it involves generics and new language features (such as lambdas), can get quite tedious and arcane. For example, look at this one that turned out to be a javac bug but did uncover a related issue in Eclipse's compiler: https://bugs.eclipse.org/bugs/show_bug.cgi?id=456459
The best bet is to report it as an Eclipse bug as I did and see if the Eclipse compiler team can/will track it down.

How to migrate an Eclipse AspectJ project to IntelliJ IDEA

At my company, we are currently working with Eclipse for our Java projects.
As me and some other coworkers would rather use IntelliJ, we took a crack at migrating our projects and failed at getting AspectJ to work.
We are using Java 7 though the projects are written in Java 6 compatility.
Before trying it out we updated to the most recent version of IDEA (14.03).
The AspectJ version is 1.7.3.
Here are the steps we took:
import the project and dependencies into IntelliJ
download and install AspectJ
Under Settings -> Java Compiler: Use ajc compiler, delegate to javac (path to aspectjtools.jar is correct as the test button indicates)
Add AspectJ libs to Global Libraries (aspectjrt.jar, aspectjtools.jar, aspectjweaver.jar, and org.aspectj.matcher.jar)
Create AspectJ facet for the one module that is using AspectJ, leave all settings as is (no aspect path defined)
Add aspectjrt to project libraries
rebuild, make etc.
LogContext is just an empty interface. Classes that want a logger appended implement this interface.
This method is injected with AspectJ. Unfortunately I am not an expert with this and the guy who implemented it left the company, so I am stuck.
In order to check general functionality, we implemented a tiny project from scratch with just three classes with the same settings as above:
public interface LogContext {}
public aspect LogContextAspect {
public void LogContext.log() {
System.out.println("Log!");
}
}
public class Aspect implements LogContext {
public static void main(String[] args) {
Aspect aspect = new Aspect();
aspect.log();
}
}
The code actually executes fine and prints out the "Log!" message, but on make I get the following error:
Error:(4, 0) ajc: The type Aspect must implement the inherited abstract method LogContext.log()
What are we missing here? In order to migrate our projects, we need AspectJ to work.
The whole system is built with Java 6 compatibility but runs on Java 7.
Thanks for your help!
Sascha
I tried with IDEA 14.1.1 Ultimate and it works nicely, even though AspectJ support in IDEA is generally not as advanced as in Eclipse, even though all in all IDEA to me is superior. But for AspectJ I often use Eclipse.
I think it would be a good idea to "mavenise" your project. This way it would work in Eclipse and IDEA. In IDEA activate auto import for Maven changes to let Maven be the leading system and IDEA just follow its settings. This works well for my AspectJ projects. But in this case I set up your example manually (no Maven). After a few steps it works now. Along the way I did not see the error message you mentioned.
Edit: I use AspectJ 1.8.5, if that makes any difference.
Edit 2: I have tried with both compiler and runtime manually set to 1.7.3, it still works.

Blackberry #Override notation error

In Eclipse, I did: Source > Clean up, and did a clean up according to these rules:
Change non static accesses to static
members using declaring type
Change indirect accesses to static
members to direct accesses (accesses
through subtypes)
Remove unused imports
Add missing '#Override' annotations
Add missing '#Deprecated' annotations
Remove unnecessary casts
Remove unnecessary '$NON-NLS$' tags
but I can't seem to compile it anymore. I get the following error:
Error preverifying class com.myapp.blackberry.Override
java/lang/NoClassDefFoundError: java/lang/annotation/Annotation
Error!: Error: preverifier failed: C:\eclipse\plugins\net.rim.ejde.componentpack6.0.0_6.0.0.29\components\bin\preverify.exe -d C:\DOCUME ...
Packaging project myapp failed (took 0.422 seconds)
When I hover over #Override, it gives me suggestion "Override cannot be resolved to a type"
I am not sure what to do at this point..
Blackberry development is built on top of j2me, which has the language features of Java 1.3. This means it doesn't support annotations. You can remove the #Override annotations and your code will work. Remember these are optional although recommended anyways.
What I do, is write //#Override instead. When/If annotations are added in the future it will be easy to do a regex replace and remove the comment marks.
Seems to be impossible:
The deal is Java ME uses version 1.4 of Java Language Specification.
You cannot use Java 5 language features.
Seems you'll have to do without annotations...

Why is javac failing on #Override annotation

Eclipse is adding #Override annotations when I implement methods of an interface. Eclipse seems to have no problem with this. And our automated build process from Cruise Control seems to have no problem with this. But when I build from the command-line, with ant running javac, I get this error:
[javac] C:\path\project\src\com\us\MyClass.java:70: method does not override a method from its superclass
[javac] #Override
[javac] ^
[javac] 1 error
Eclipse is running under Java 1.6. Cruise Control is running Java 1.5. My ant build fails regardless of which version of Java I use.
The #Override annotation spec changed in Java 1.6. In Java 1.5, the compiler did not allow the #Override annotation on implemented interface methods, but in 1.6 it does. First search result I found is a blog post here.. It was not well documented, but it did change.
Eclipse is adding it because your Eclipse is set for 1.6 compliance. You should try to keep your build and eclipse environments on the same version of Java. It's unclear to me by your specifying Cruise Control is running Java 5 on whether or not it is compiling using a separate JDK6 or not.
Separate from the above 1.5 vs 1.6 #Override annotation rules, remember that Eclipse has its own compiler implementation (not javac) and will occasionally have different behavior. Whenever something compiles in Eclipse, but not Ant or Maven, you will need to find a way to make both compilers happy.
I can't really explain the problem you're seeing but it seems to be related to the fact that JDK 5 will not allow #Override on implemented methods of an interface, only on overridden methods present in a super class.
JDK 6 will allow #Override on any of them.
If your ant build fails it may be passing a source parameter to javac, asking for JDK 5 compliance.
The direct answer to the question "Why" an error is raised by javac when #Override is used in the context of a method implementation is actually in the java specifications:
"The rationale for this is that a concrete class that implements an interface will necessarily override all the interface's methods irrespective of the #Override annotation, and so it would be confusing to have the semantics of this annotation interact with the rules for implementing interfaces."
See http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html#9.6.1.4
But apparently someone changed his mind for java 1.6 and 1.5 u21...
#Override tags for implemented methods are new to Java 1.6. In Java 1.5 #Override is only correct when overriding a method in a base class. Read more here and here.
A lot of people, including me, got busted by this. See here for a bigger SO discussion
Eclipse would be pointing to 1.6 version of Java rather than 1.5.
See here for configuring java version in eclipse.
Ensure that there is only one definition of that interface.
Example:
HttpServletRequest
This is an interface with different specs depending on provider.
Compare pax-web-jetty and apache-felix-jetty. They have different methods.
I have had the same problem when building a project with ANT. The solution to the problem was to change the following property inside the build.properties file:
javac.compiler=org.eclipse.jdt.core.JDTCompilerAdapter
to:
javac.compiler=modern
That solved the problem and the project got compiled and deployed successfully.

Categories