how to suppress this warning on the `var` keyword? - java

The message is:
Warning:(ROW, COLUMN) java: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array
Am using Lombok 1.18.12 from Java 11 targeting version 7, that's how come those var are in there.
How to suppress? What to throw in #SuppressWarnings(...)?
[...]
var excepted = false;
[...]

Just don't use lombok's var, and use the one built into java. That, or, downgrade to java8.
Lombok's var does effectively the same thing as java10+'s 'var', except lombok allows compound assignments and does not allow non-denotable types (java10 var allows non-denotables, but doesn't allow compound). These are two exotic concepts you're unlikely to need :)

Related

Nullable types in kotlin annotation processor

I'm working on annotation processor for Kotlin and because the processed elements are in Java I don't receive nullables as ? instead with a #Nullable annotation and that's fine, but I'm facing a problem with receiving null parameters in types and in higher order functions, for normal parameters.
var someNullField: String? = ""
I will receive java.lang.String at process with #org.jetbrains.annotations.Nullable in its annotations.
But List<String?> for example will return me java.util.List<java.lang.String> without any annotations not in the main element not in the type arguments which results in a unknown nullability state
I tried using javax.lang.model.util.Types to find some sort of result but nothing.
Some of the code that i'm using now:
val utils = processingEnvironment.typeUtils
val type = fieldElement.asType()
if (type is DeclaredType) {
val typeElement = utils.asElement(type)
type.typeArguments
.forEach {
//Trying different ways and just printing for possible results
val capture = utils.capture(it)
val erasure = utils.erasure(it)
val element = utils.asElement(it)
printMessage("element: $element isNullable: ${element.isNullable()} isNotNull: ${element.isNotNull()}\ncapture: $capture isNullable: ${capture.isNullable()} isNotNull: ${capture.isNotNull()}\nerasure: $erasure isNullable: ${erasure.isNullable()} isNotNull: ${erasure.isNotNull()}")
}
}
All help will be appreciated.
A bit of necessary history: as of Java 6 (when the Mirror API was made public) Java annotations could not be used on anything, but the same kinds of top-level elements, accessible via reflection. You could annotate classes, methods and fields, but could not annotate type arguments (List<String>) or local variables (String value = ...). Sun/Oracle engineers have acknowledged that limitation, and in Java 8 the so-called "type annotations" were born.
Type annotations can target type of anything: type of local variable, array component type, type variable type and even return type (later annotation is placed similarly, but is distinct from the old-school annotations on the method!). Type annotations are created via new #Target value: ElementType#TYPE_USE.
When Kotlin people write
List<String?>
That really means
List<#Nullable String>
which can be read as: "the list of nullable String elements".
Since the type itself is being targeted, you are expected to obtain annotations by examining it's original TypeMirror (don't bother with erased or captured TypeMirrors, they don't have enough connection to source code to retain the annotations). Coincidentally, the Mirror API was refactored, resulting in the new interface AnnotatedConstruct, and conveniently making TypeMirror it's descendant.
Now the bad news: by the time of Java 8 release the support for inspecting type annotations apparently wasn't production-ready, so it got butchered. The JSR has been rewritten to imply, that "TypeMirror#getAnnotationMirrors" is supposed to return nothing.
The bits of support, that were removed from public API, are still available via Oracle's vendor-specific Tree API (supported in javac only). The TypeMirror, returned by Tree#getTypeMirror may contain the annotation the way you are expecting it to. But since it is buggy, you will only be able to get annotations via series of hacks, and ultimately, this won't work at all times (such as in case of nested type arguments). See this question for some research in that direction.
The fix for that mess was merged in Java 9. I haven't tested it yet, but it looks like TypeMirror#getAnnotationMirrors might finally work. There are no plans to backport the fix to the older Java version.

Set without Datatype mentioned

Is it fine to write following?
Set<Integer> integs = new HashSet<>();
Inside <>, is it fine to leave it as empty?
As from Java 7, the compiler will infer the data type of the hash set without the need to write it twice.
Note though that there are some scenarios where the compiler might fail to infer the type, so you could get compilation errors for more complex scenarios.
More of that here.
Yes this is a feature introduced in Java 7 where the <> is called the diamond operator. See http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html.
Yes if you're using java 7 or higher as described in documentation
You can replace the type arguments required to invoke the constructor of a generic class with an empty set of type parameters (<>) as long as the compiler can infer the type arguments from the context. This pair of angle brackets is informally called the diamond.
Yes. In your case, It'll take it as integer in Java 7 and later versions. Please find the confirmation from the Java documentation. http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html

Is there a difference between explicitly putting the type into the diamond operator vs letting java figure it out?

Is there any difference between initialization via:
MyWrapper<String> wrapper = new MyWrapper<String>();
vs initialization via:
MyWrapper<String> wrapper = new MyWrapper<>();
Is there any reason why one would want to use the former over the latter? I see a lot of the former; I'm not sure if it's just because that's what people are used to, or there's a reason you'd want to write it that way.
The latter is only available since Java 7. That's why you often see the former. The latter is equivalent, and shorter.
JDK 7 allows to not redefine this "redundant" diamond at initialization time.
It's just a shorter syntax.
With JDK <= JDK 6, the latter doesn't work, you have to use the former.
It is largely because while Java 7 is the current version, a lot of code still uses Java 6, which does not support the latter form.
In essence, Java 7 compilers are better at infering generic types.
Before Java 7, the former was required. Now with type inferencing, the latter is preferred.

Infer variable type in Java / Eclipse, like C#'s "var"

I like "var" from C# and "def" from Groovy, and I find writing out types in Java to be a pain.
Say I'm writing code like:
List<LongTypeName> results = new ArrayList<LongTypeName>();
or
Map<TypeNameOne,TypeNameTwo> someLookup = fetchMeMyLookup();
What's the easiest way to get this done in Java + Eclipse?
I'm especially interested in the case where I'm not 100% sure what the type will be when I start the line.
My current strategy is to always declare variables as "int", then go back to the start of the line and do "ctrl-1", and accept the type that Eclipse has inferred. Is there any better alternative?
What I would love is to be able to type "def" or "var" and have Eclipse auto-correct this to the correct type as soon as it can figure it out.
(Maybe I should just be programming in Groovy)
Type new ArrayList<LongTypeName>();
Type Ctrl+2+L to create a new local variable
Both type type are 'active' - you can tab through them an cycle through selections. In this example, the name proposals are list and arrayList and the type proposals are all possible interfaces and superclasses of ArrayList<String>, : List<String, Collection<String> etc.
Type:
someLookup = fetchMeMyLookup();
Then click on someLookup and hit Ctrl+1 for the quick fix of "Create local variable someLookup"
Java 10 has introduced type inference for local variables.
You may now use the special (reserved) type name var, e.g.:
var results = new ArrayList<LongTypeName>();
var someLookup = fetchMeMyLookup();
See JEP 286 for details.

What is the equivalent of the C# 'var' keyword in Java?

One use of the var keyword in C# is implicit type declaration. What is the Java equivalent syntax for var?
There is none. Alas, you have to type out the full type name.
Edit: 7 years after being posted, type inference for local variables (with var) was added in Java 10.
Edit: 6 years after being posted, to collect some of the comments from below:
The reason C# has the var keyword is because it's possible to have Types that have no name in .NET. Eg:
var myData = new { a = 1, b = "2" };
In this case, it would be impossible to give a proper type to myData. 6 years ago, this was impossible in Java (all Types had names, even if they were extremely verbose and unweildy). I do not know if this has changed in the mean time.
var is not the same as dynamic. variables are still 100% statically typed. This will not compile:
var myString = "foo";
myString = 3;
var is also useful when the type is obvious from context. For example:
var currentUser = User.GetCurrent();
I can say that in any code that I am responsible for, currentUser has a User or derived class in it. Obviously, if your implementation of User.GetCurrent return an int, then maybe this is a detriment to you.
This has nothing to do with var, but if you have weird inheritance hierarchies where you shadow methods with other methods (eg new public void DoAThing()), don't forget that non-virtual methods are affected by the Type they are cast as.
I can't imagine a real world scenario where this is indicative of good design, but this may not work as you expect:
class Foo {
public void Non() {}
public virtual void Virt() {}
}
class Bar : Foo {
public new void Non() {}
public override void Virt() {}
}
class Baz {
public static Foo GetFoo() {
return new Bar();
}
}
var foo = Baz.GetFoo();
foo.Non(); // <- Foo.Non, not Bar.Non
foo.Virt(); // <- Bar.Virt
var bar = (Bar)foo;
bar.Non(); // <- Bar.Non, not Foo.Non
bar.Virt(); // <- Still Bar.Virt
As indicated, virtual methods are not affected by this.
No, there is no non-clumsy way to initialize a var without an actual variable.
var foo1 = "bar"; //good
var foo2; //bad, what type?
var foo3 = null; //bad, null doesn't have a type
var foo4 = default(var); //what?
var foo5 = (object)null; //legal, but go home, you're drunk
In this case, just do it the old fashioned way:
object foo6;
If you add Lombok to your project you can use its val keyword.
http://projectlombok.org/features/val.html
JEP - JDK Enhancement-Proposal
http://openjdk.java.net/jeps/286
JEP 286: Local-Variable Type Inference
Author Brian Goetz
// Goals:
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>
With the release of JDK 10 on March 20, Java now includes a var reserved type name (not a keyword—see below) as specified in JEP 286. For local variables, the following is now valid in Java 10 or higher:
var map = new HashMap<String, Integer>();
The var reserved type name in Java is nearly identical to the var keyword in C# in that both allow for implicit typing (see below for important differences). var in Java can only be used for implicit type inference in the following contexts (as enumerated in JEP 286: Goals):
local variables with initializers
indexes in the enhanced for-loop
locals declared in a traditional for-loop
Therefore var cannot be used for fields, return types, class names, or interface names. Its rationale is to remove the need for including long type names when declaring and defining local variables, as stated in JEP 286 (authored by Brian Goetz):
We seek to improve the developer experience by reducing the ceremony
associated with writing Java code, while maintaining Java's commitment
to static type safety, by allowing developers to elide the
often-unnecessary manifest declaration of local variable types.
var Scoping in Java
It should be noted that var is not a keyword in Java, but rather a reserved type name. As quoted from JEP 286:
The identifier var is not a keyword; instead it is a reserved type
name. This means that code that uses var as a variable, method, or
package name will not be affected; code that uses var as a class or
interface name will be affected (but these names are rare in practice,
since they violate usual naming conventions).
Note that since var is a reserved type name and not a keyword, it can still be used for package names, method names, and variable names (along with its new type-interference role). For example, the following are all examples of valid uses of var in Java:
var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var;
As quoted from JEP 286:
This treatment would be restricted to local variables with
initializers, indexes in the enhanced for-loop, and locals declared in
a traditional for-loop; it would not be available for method formals,
constructor formals, method return types, fields, catch formals, or
any other kind of variable declaration.
Differences Between var in Java & C
This is one notable difference between var in C# and Java include the following: var can be used as a type name in C# but cannot be used as a class name or interface name in Java. According to the C# documentation (Implicitly Typed Local Variables):
If a type named var is in scope, then the var keyword will resolve to
that type name and will not be treated as part of an implicitly typed
local variable declaration.
The ability to use var as a type name in C# creates some complexity and introduces some intricate resolution rules, which are avoided by var in Java by disallowing var as a class or interface name. For information on the complexities of var type names in C#, see Restrictions apply to implicitly-typed variable declarations. For more information on the rationale behind the scoping decision for `var in Java, see JEP 286: Scoping Choices.
I have cooked up a plugin for IntelliJ that – in a way – gives you var in Java. It's a hack, so the usual disclaimers apply, but if you use IntelliJ for your Java development and want to try it out, it's at https://bitbucket.org/balpha/varsity.
It will be supported in JDK 10. It's even possible to see it in action in the early access build.
The JEP 286:
Enhance the Java Language to extend type inference to declarations of local variables with initializers.
So now instead of writing:
List<> list = new ArrayList<String>();
Stream<> stream = myStream();
You write:
var list = new ArrayList<String>();
var stream = myStream();
Notes:
var is now a reserved type name
Java is still commitment to static typing!
It can be only used in local variable declarations
If you want to give it a try without installing Java on your local system, I created a Docker image with JDK 10 installed on it:
$ docker run -it marounbassam/ubuntu-java10 bash
root#299d86f1c39a:/# jdk-10/bin/jshell
Mar 30, 2018 9:07:07 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
| Welcome to JShell -- Version 10
| For an introduction type: /help intro
jshell> var list = new ArrayList<String>();
list ==> []
A simple solution (assuming you're using a decent IDE) is to just type 'int' everywhere and then get it to set the type for you.
I actually just added a class called 'var' so I don't have to type something different.
The code is still too verbose, but at least you don't have to type it!
As of Java 10, the equivalent is ... var.
You can take a look to Kotlin by JetBrains, but it's val. not var.
Java 10 did get local variable type inference, so now it has var which is pretty much equivalent to the C# one (so far as I am aware).
It can also infer non-denotable types (types which couldn't be named in that place by the programmer; though which types are non-denotable is different). See e.g. Tricks with var and anonymous classes (that you should never use at work).
The one difference I could find is that in C#,
If a type named var is in scope, then the var keyword will resolve to that type name and will not be treated as part of an implicitly typed local variable declaration.
In Java 10 var is not a legal type name.
I know this is older but why not create a var class and create constructors with different types and depending on what constructors gets invoked you get var with different type. You could even build in methods to convert one type to another.
Lombok supports var but it's still classified as experimental:
import lombok.experimental.var;
var number = 1; // Inferred type: int
number = 2; // Legal reassign since var is not final
number = "Hi"; // Compilation error since a string cannot be assigned to an int variable
System.out.println(number);
Here is a pitfall to avoid when trying to use it in IntelliJ IDEA. It appears to work as expected though including auto completion and everything. Until there is a "non-hacky" solution (e.g. due to JEP 286: Local-Variable Type Inference), this might be your best bet right now.
Note that val is support by Lombok as well without modifying or creating a lombok.config.
You can, in Java 10, but only for Local variables, meaning,
You can,
var anum = 10; var aString = "Var";
But can't,
var anull = null; // Since the type can't be inferred in this case
Check out the spec for more info.
In general you can use Object class for any type, but you have do type casting later!
eg:-
Object object = 12;
Object object1 = "Aditya";
Object object2 = 12.12;
System.out.println(Integer.parseInt(object.toString()) + 2);
System.out.println(object1.toString() + " Kumar");
System.out.println(Double.parseDouble(object2.toString()) + 2.12);
This feature is now available in Java SE 10. The static, type-safe var has finally made it into the java world :)
source: https://www.oracle.com/corporate/pressrelease/Java-10-032018.html

Categories

Resources