Why I can't use Override annotations at Android? - java

I'm developing an app to android but I can't use the Override annotations. It keeps saying that the method must override a superclass method, which does. I'm using Java 1.7 and Android API 8 (2.2). Using Eclipse.
Any ideas?
EDIT:
Example
#Override
public int getCount() {
// TODO Auto-generated method stub
return this.data.size();
}
But the compiler don't let me use #Override, saying its not a superclass method. I'm exetending BaseAdapter.

You should be using java 1.6 when building android projects. Java 1.7 isn't compatible with the current set of Android tools. Change your projects to use 1.6 and this problem should go away
In eclipse:
Right click project -> properties -> Java Compiler -> switch all references to 1.7 to 1.6

You can use #Override annotation. If you get this error, it means you have a mistake in the prototype of the method, or you are not extending what you want to extend.
For example, on API level 8, the following will give you the error, as the method introduced in API 11:
#Override
public void startActivities (Intent[] intents){
}

Related

At java code, how i can check jdk version to compile below java code?

// monitor.freeMemory = bean.getFreeMemorySize();//jdk 15
// monitor.maxMemory = bean.getTotalMemorySize();
// monitor.systemLoadAverage = bean.getCpuLoad();
monitor.freeMemory = bean.getFreePhysicalMemorySize();//jdk 13
monitor.freeMemory = bean.getTotalPhysicalMemorySize();
monitor.systemLoadAverage = bean.getSystemCpuLoad();
I want to use above code without comment
Java does not have a conditional compilation, so some workarounds have to be made. One approach is to make an interface like this:
interface monitor {
public void getFree();
public void getTotal();
public void getCpu();
}
Implementation of this interface should call appropriate methods using reflection depending on the JVM version. Something like this (conceptually):
public void getFree() {
if (System.getProperty("java.version").equals(JDK_15_VERSION)) {
Class myclass = Class.forName("my.class.JDK_15_NAME");
Object myobject = myclass.newInstance();
Method method = myclass.getDeclaredMethod("FREE_MEM_JDK_15_METHOD", null);
method.invoke(obj, null);
}
else {
Class myclass = Class.forName("my.class.JDK_13_NAME");
Object myobject = myclass.newInstance();
Method method = myclass.getDeclaredMethod("FREE_MEM_JDK_13_METHOD", null);
method.invoke(obj, null);
}
}
Until now this is not possible. At least not something that you think of, like a clean If/else condition. If we hack deep enough we can make it happen, in a very dirty way though.
That's the reason that methods get deprecated. They don't throw things out of the window so that the project must be compiled with another method. They provide for enough time those deprecated methods so that you can move forward safely.
That is also the case in your question. Your project could compile with either JDK 13 or JDK 15 using the same code.
com.sun.management.OperatingSystemMXBean bean = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
bean.getFreePhysicalMemorySize();
bean.getTotalPhysicalMemorySize();
bean.getSystemCpuLoad();
This code will be able to compile and function from JDK 11 up to all new versions of JDK. If you switch to JDK 14 though, you will receive a deprecated warning.
Considering that JDK 11 is a LTS version, they could not throw methods out of the window. Most probably they will be available also to the next LTS version.

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

Is it possible to add #Override keyword with conditional define (I mean on some API version only)

I want to override the actionmode. However the base class have now starting at API 23+ the public method onWindowFocusChanged. in my code I override like this
#Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
}
but i want also to target api < 23, and in api < 23 if i call MyObject.onWindowFocusChanged i will receive a E/AndroidRuntime(23165): java.lang.NoSuchMethodError: android.view.ActionMode.onWindowFocusChanged
is it possible to say the keyword #Override only if api >= 23 and else to omit it ?
The #Override annotation just hints the compiler to check the parent(s) class(es) for the same signature and helps you avoid assuming a method overrides something when it really doesn't. Once compiled, it does not affect the functionality of that method.
If you indeed to only override this method when using api>=23 (as opposed to not supporting older APIs at all), you should not use this annotation.

Is it safe to comment out the "#Override"?

To get my code to compile - which contained the following:
public class ContactsActivity extends ListActivity implements AdapterView.OnItemClickListener {
Cursor mContacts;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Return all contacts, ordered by name
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME };
mContacts = managedQuery(ContactsContract.Contacts.CONTENT_URI,
projection, null, null, ContactsContract.Contacts.DISPLAY_NAME);
// Display all contacts in a ListView
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, mContacts,
new String[] { ContactsContract.Contacts.DISPLAY_NAME },
new int[] { android.R.id.text1 });
setListAdapter(mAdapter);
// Listen for item selections
getListView().setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
. . .
...I had to comment out the "#Override" above the onItemClick() event handler. Is this safe? Should I just shrug my shoulders and say, "OK, that works, I'll forget about it" or is there evil afoot/a hidden problem lurking?
as per my suggestion, it is not good to remove that line. you need to change to JDK version in your eclipse then you will not get such errors. Follow, following steps for it,
Right Click on your Project & select Properties.
Then from the left section Select Java Compiler & select the Version of the JDK you installed. If it is already selected then de-select it & try it.
If you had to comment out the #Override, then your compiler's JDK compliance level isn't set to 1.6, which it should be for Android development. If you're using Eclipse, right click on the project name and select "Properties". Then select "Java Compiler" and adjust as necessary. (You probably inherited a lower JDK compliance level from the workspace. If appropriate, change the compliance level for the workspace instead. This will save having to fix the same problem with new projects.)
But to answer your question: it's safe to comment out #Override. It's just not so great to be using a lower compliance level.
You java version is set to less than 1.6. Starting there, interfaces and not just methods can be market as Override. Right click the project -> Properties -> Java Compiler -> Compiler compliance level to 1.6
From the Java docs:
#Override - the #Override annotation informs the compiler that the
element is meant to override an element declared in a superclass
(overriding methods will be discussed in the the lesson titled
"Interfaces and Inheritance").
// mark method as a superclass method
// that has been overridden
#Override
int overriddenMethod() { }
While it's not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with #Override
fails to correctly override a method in one of its superclasses, the
compiler generates an error.
It depends. If your compiler is set to target java 5, and the onCreate method is inherited from the interface then yes. Java 5 doesn't support the override annotation on interface methods, whereas Java 6 expects it. This may itself be an indication that your JDK is set up wrong, if you're expecting to target Java 6, what you may be getting is Java 5.
if you'd commented it out, you would not override the methods. So you'd actually do nothing. (My opinion)

How do I build a Java project with Java 6 against Java 1.4 libraries?

I've got a project that was originally written for Java 1.4, but I only have Java 6 on my Mac and I cannot install Java 1.4.
Normally, I'd use a line like this to compile:
javac -source=1.4 -target=1.4 MyClass.java
However, MyClass.java implements the java.sql.ResultSet interface, which added several new methods in Java 6, so I get compile errors like:
MyClass is not abstract and does not override abstract method
updateNClob(java.lang.String,java.io.Reader) in java.sql.ResultSet
I cannot simply implement the missing methods because many use generics, which are not available in Java 1.4.
It seems a solution would be to obtain and compile against the Java 1.4 JARs. So, I've got a few questions:
Is there a better way?
How do I specify to my Java 1.6 javac that I'd like to use the 1.4 JARs instead of the Java 6 JARs?
Will this even work, and if so, will the project run on Java 1.4 as well as Java 6?
How do I do this in Maven?
Thanks!
Your situation seems to be quite contrived. I'll try to simplify matters. At first, I am going to ignore your question about Maven.
So let me first state some facts:
-source=1.4 means: Dear compiler, please accept only language constructs --- not library features --- which were available with javac of JDK 1.4.
-target=1.4 means: Dear compiler, please write class files in a binary file format which is compatible with a JRE 1.4.
I gather that you are interested in load-time compatibility with JDK 1.4, i.e. you want that the class files produced in your setup can be loaded by JDK 1.4. Is that right?
Do you also want to support source compatibility? I.e. do you want to allow others to compile your code on a JDK 1.4?
If the answer to the last question is yes, I would try to install JDK 1.4 on OS X. It supports multiple installed JDKs. So I am pretty sure it is possible. If that is no option use:
-source=1.4 -target=1.4 -bootclasspath=[path/to/1.4.jar]
Note, do not use -Xbootclasspath. This changes the boot classpath of the jvm executing javac.
If the answer to the above question is no. You can dispose of -source=1.4 allowing you to use generics and other Java 5 enhancement in your code. But you still have to provide binary compatibility by using:
-target=1.4 -bootclasspath=[path/to/1.4.jar]
Another option would be to use Retroweaver.
After re-reading your question, I'd like add that you have to get hold of JDK 1.4 variant of the jdbc class files. Otherwise you'll run into the compiler errors you've shown in your question.
Unless you are a JDBC vendor, it is unwise to implement interfaces like this one.
Consider using a proxy to maintain compatibility across JVM versions.
Migrating to a proxy is accomplished as follows. Consider this ResultSet implementation:
public class ResultSetFoo implements ResultSet {
public String getString(int columnIndex) throws SQLException {
return "foobar";
}
// other Java 1.4 methods
This would be changed so no classes implement ResultSet:
public class ResultBar {
public String getString(int columnIndex) throws SQLException {
return "foobar";
}
// other method signatures matching the 1.4 ResultSet, as before
You would then need to build a mapping of methods between the two types at runtime (a primitive form of duck-typing:)
private static final Map RESULT_SET_DUCK = initResultSet();
private static Map initResultSet() {
Map map = new HashMap();
Method[] methods = ResultSet.class.getMethods();
for (int i = 0; i < methods.length; i++) {
try {
Method match =
ResultBar.class.getMethod(methods[i].getName(),
methods[i].getParameterTypes());
map.put(methods[i], match);
} catch (SecurityException e) {
throw new IllegalStateException(e);
} catch (NoSuchMethodException e) {
// OK; not supported in 1.4
}
}
return map;
}
This allows you to invoke the ResultBar type by proxy:
/** Create a java.sql.ResultSet proxy */
public static ResultSet proxy(final ResultBar duck) {
class Handler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method proxiedMethod = (Method) RESULT_SET_DUCK.get(method);
if (proxiedMethod == null) {
throw new UnsupportedOperationException("TODO: method detail");
} else {
return invoke(proxiedMethod, duck, args);
}
}
private Object invoke(Method m, Object target, Object[] args)
throws Throwable {
try {
return m.invoke(target, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
}
return (ResultSet) Proxy.newProxyInstance(null, RSET, new Handler());
}
Such implementations should allow code compiled in one JVM to be used in future JVMs even if new methods are added. Existing method signatures are unlikely to change because it is one thing to make database vendors do some work; something else to make all API consumers change.
You may need to change how class instances are created. You can no longer use a constructor directly:
ResultSet nonPortable = new ResultSetFoo();
//becomes...
ResultSet portable = proxy(new ResultBar());
If you're already employing a factory/builder/etc. pattern this bit is easy.
Although reflection is relatively cheap in the latest JVMs it is less so in older versions; this may have a detrimental effect on performance.
How do I specify to my Java 1.6 javac that I'd like to use the 1.4 JARs instead of the Java 6 JARs?
In Win. & *nix it would be by specifying the bootclasspath option. See javac: Cross-Compilation Options for more details.

Categories

Resources