In my java program, I have imported some java packages in one class.
but in there 1 or 2 packages were crossed out.
Why that happened?
How to solve this cross out to make uncrossed?
For the sake of completeness, there is a special case which looks like this in Eclipse:
In the case above there exist three is() methods, which all are statically imported. Hoovering the crossed out method name doesn't give any information, and there isn't a warning marker like there is for #Deprecated classes. In other words, it can be tricky to understand what it means.
In this case, one of the is() methods is #Deprecated, causing the behaviour.
This behaviour was discussed here, a question which was closed as a duplicate.
Those classes are marked as #Deprecated.
This means that the compiler advises not to use them, because they can bring you problems.
A program element annotated #Deprecated is one that programmers are
discouraged from using, typically because it is dangerous, or because
a better alternative exists. Compilers warn when a deprecated program
element is used or overridden in non-deprecated code.
Check the javadoc(s) of the deprecated classes to check which classes to use instead.
Related
I'm programming a Config class that reads a file and provides config parameters as a Map.
Parameters can be accessed by conf.get("LogLevel") or conf.getLogLevel().
The first function just reads from the map and returns the value (that can be null or invalid) while the second function converts the value to a LogLevel and returns a default value when no valid value is given.
Therefore I want to discourage Programmers from using the genereral get(), but there are special cases where this method is useful so I cant just make it protected.
Right now I use #Deprecated but I dont think this is a good solution because it is only ment for methods that will be removed in the future. (Correct me if I'm wrong there, thats what SonarLint told me about the #Deprecated annotation)
/**
* #Deprecated When possible, use the key-specific getter instead
*/
public String get(String key) {
return values.get(key);
}
public int getLogLevel() {
return Log.getLogLevel(values.get(LOG_LEVEL), Log.getLogLevel(defaultValues.get(LOG_LEVEL)));
}
Well, if #Deprecated is not the solution, you are left with only one option. Put message that notes that the usage is "discouraged" (except for the special cases) into the javadocs ... and hope that people are going to read the javadocs.
Defining your own custom annotation will not help because you can't get your users to use an annotation processor that will recognize it.
Likewise, you can't do it via custom rules for FindBugs, PMD, Sonar and so forth because that requires your users to customize their installations of those products.
(Though ... if this is an in-house product and all of your users use a common CI server ... you could possibly do the checks in the CI server. It depends if you can define custom rules that can reliably distinguish the general "discouraged" use-cases from the special cases. This will also entail convincing your co-workers that this is a good idea.)
In my opinion, the #Deprecated tag would be better than all of the above. For the special cases, encourage people to judiciously add #SuppressWarning("deprecation") in the cases where the usage is necessary.
I don't think this is a good solution because it is only meant for methods that will be removed in the future.
This is incorrect. Possible future removal is only one of the example reasons for deprecation listed in the #Deprecated javadoc (Java 11 version). Other reasons listed there are:
"the tagged element's usage is likely to lead to errors",
"it may be changed incompatibly [...] in a future version",
"it has been superseded by a newer, usually preferable alternative", or
"it is obsolete".
Note that these are listed as example reasons ... which means that you could deprecate for other reasons.
This is also consistent with the older "when to deprecate" guidance here.
IMO, your "discouraged" scenario is covered by that.
If you arrived here and looking for android solution there's #Discouraged annotation in androidx
Okay, so recently I decompiled some code I had written years ago. So, the decompiler I use does not decompile the anonymous classes, since the Java compiler compiled them as separate classes.
So, I have a file called TitleScreen, and other files following with TitleScreen$1, TitleScreen$2. Simple. But....why the numbers? The class isn't named with an int, that's impossible. How would these be structured? Do I just give them a random name like optionsClick(), worldsClick()?
Thanks!
Those are the names the Java compiler generates for anonymous classes.
You can give them whatever name you want.
The compiler is more powerful than us mere programmers and can name classes with that funny syntax. Perhaps it does it that way cause it knows it is "safe": no user defined class (see comments below) is likely to have that name.
As for what you should name the decompiled classes, I'd suggest TitleScreen.Anon1, TitleScreen.Anon2 if you make them inner classes, or TitleScreen_Anon1 if their own classes. That way you have some reference back to the original code if needed.
Now, we know that Java 8 has introduced default and static methods in interfaces.
Interfaces were originally introduced in Java to avoid the diamond problem that occurred in C++, in multiple inheritance.
But along with the introduction of default methods in interfaces in Java 8, now, Java has also introduced the diamond problem, which it avoided in previous versions.
Default methods are not compulsorily needed to be overridden.
But when a diamond problemoccurs using interfaces, the class implementing those interfaces must override the default methods.
So now, I have three questions in my mind:
Why is the need to have default methods?
Couldn't we have multiple inheritance through classes itself, in place of having default methods in interfaces?
And what was the need to avoid diamond problem in the previous versions, if they had to introduce it in Java 8 anyway?
Any good explanation or any link for explanation?
PS I did not find any link on the internet containing any good article on this.
All they said is that an abstract class gives you more concreteness.
As in, abstract classes can have constructors but interfaces cannot.
So again, I want to know, If abstract classes are more concrete, and can have constructors,
and anyways Java has introduced the diamond problem, why should we have interfaces now? Wouldn't abstract classes be good enough as a stand alone for multiple inheritance?
No, it didn't reintroduce the diamond problem, because interfaces still can't have any state, and default methods may not be final.
So, when you choose to implement two interfaces, you still have all the freedom you want to implement the default methods, either by choosing one of the provided default implementations, or by providing your own implementation. But you'll never have a problem of inheriting conflicting state from both interfaces, or inheriting two different final methods and not being able to resolve the conflict.
So, here are the answers to your questions:
To be able to introduce new methods in existing interfaces without breaking backward compatibility: existing implementations will automatically implement these methods since their implementation is in the base interface.
No, because that would introduce a diamond problem.
Irrelevant
Regarding Point 1:
In order to support lambda expression for all collection classes, like forEach method, it was necessary to add something which will have backward compatibility.
see this video for detail Lambda Peak Under the hood
Default methods make it possible to enhance an existing interface while providing binary compatibility with former versions of the interface to existing users.
See more here https://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html
I have noticed in SONAR that I have a violation that is called IllegalType in my java Code. I looked for this and in Checkstyle explain about it this :
Checks that particular class are never used as types in variable declarations, return values or parameters. Includes a pattern check that by default disallows abstract classes.
Rationale: Helps reduce coupling on concrete classes. In addition abstract classes should be thought of a convenience base class implementations of interfaces and as such are not types themselves.
But I don't understand really why is this a problem in my code. If anyone can explain me better maybe with an example it could be great!. Thanks at all.
What Aaron Digulla said in his comments is a good practice for sure. However I also found this IllegalType issue with my own Abstract Classes (instead of interfaces) which don't seem to me to be pretty clear. I understand the benefits of using intefaces insteaf of classes, and I also understand that abstract classes are partially classes (so much more a class than a interface) but I don't see the benefits of this rule, as I can find cases where I can return a concrete class (no abstract) which is a superclass of what I'm actually returning.
Not all violations that Sonar finds are for everyone. The check IllegalType (docs) tries to make sure you don't use classes that most developers deem "broken" in some way like Vector (use ArrayList instead).
Other classes shouldn't be used as a return type. Always return List instead of ArrayList, Set instead of HashSet, Map instead of HashMap - that way, consumers of your code don't know any unnecessary details about your implementation. If you find you need to replace HashMap with TreeMap (or vice versa) in a method, that will be much more simple if you don't have to change all the places as well where this method was called.
Generally, the check isn't a problem as such (your code works) but fixing those will make your code easier to maintain in the future.
I found that there seem to be 2 general solutions:
don't obfuscate what is referred to through the reflection API [Retroguard, Jobfuscate]
replace Strings in reflection API invocations with the obfuscated name.
Those solutions work only for calls within the same project - client code (in another project) may not use the reflection API to access non-public API methods.
In the case of 2 it also only works when the Reflection API is used with Strings known at compile-time (private methods testing?). In those cases dp4j also offers a solution injecting the reflection code after obfuscation.
Reading Proguard FAQ I wondered if 2 otherwise always worked when it says:
ProGuard automatically handles
constructs like
Class.forName("SomeClass") and
SomeClass.class. The referenced
classes are preserved in the shrinking
phase, and the string arguments are
properly replaced in the obfuscation
phase.
With variable string arguments, it's generally not possible to determine
their possible values.
Q: what does the statement in bold mean? Any examples?
With variable string arguments, it's generally not possible to determine their possible values.
public Class loadIt(String clsName) throws ClassNotFoundException {
return Class.forName(clsName);
}
basically if you pass a non-constant string to Class.forName, there's generally no way for proguard or any obfuscation tool to figure out what class you are talking about, and thus can't automatically adjust the code for you.
The Zelix KlassMaster Java obfuscator can automatically handle all Reflection API calls. It has a function called AutoReflection which uses an "encrypted old name" to "obfuscated name" lookup table.
However, it again can only work for calls within the same obfuscated project.
See http://www.zelix.com/klassmaster/docs/tutorials/autoReflectionTutorial.html.
It means that this:
String className;
if (Math.random() <= 0.5) className = "ca.simpatico.Foo";
else className = "ca.simpatico.Bar";
Class cl = Class.forName(className);
Won't work after obfuscation. ProGuard doesn't do a deep enough dataflow analysis to see that the class name which gets loaded came from those two string literals.
Really, your only plausible option is to decide which classes, interfaces, and methods should be accessible through reflection, and then not obfuscate those. You're effectively defining a strange kind of API to clients - one which will only be accessed reflectively.