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
Related
I have an ArrayList of Strings, and am adding a method to sort the ArrayList
list.sort(Comparator.comparing(x -> x.length()));
When I write x and press ctrl + space eclipse does not suggest the methods of the String class, but only shows methods of the Object class.
Please help me configure eclipse to show the exact method suggestions in this case.
In regular cases eclipse is exact.
This is a two-fold issue, one with eclipse, and one with java semantics.
Java Semantics
A quick example:
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
myList.sort(Comparator.comparing(x -> x.|));
}
Assume you press ctrl + space at the | (cursor) position. Then eclipse has to infer a lot of information to know, that x is in fact an element of type String. First, the list's generic type String must be known (it is, eclipse can deduce this). Then the Comparator.comparing method needs to know, that it must return an instance of a Comparator which compares Strings, which eclipse could deduce, but here is the first issue: The Comparator could be one that compares not just Strings, but also any other kind of Object. What if you wanted to pass a method to myList.sort that is more general than the generic Comparator<String>? To be more precise: The List.sort method can take (in your case) any Comparator of type Comparator<? super String>. And ? super String is already either Object or String.
So in your example. the type of x could just be an object, eclipse cannot ultimately decide. However, you can write your lambda expression differently, to make it clear:
myList.sort(Comparator.comparing((String x) -> x.|));
In this case, the completion suggestion could be more helpful (depending on the version of eclipse).
eclipse AST issues with incomplete lambdas
An incomplete lambda expression is more often than not such an upset in the syntax of the entire file, that eclipse cannot determine the syntax tree at that position correctly. That means, that eclipse cannot deduce, that the code you are writing is supposed to be a lambda expression, where x is the parameter of the lambda function, and you want to complete that. This issue could be addressed, if the tokenizer and AST-parser of eclipse are adapted accordingly (which might have already been tried). Whether this is possible at all, I cannot answer. I only know it helps, to write a "full" lambda, with a method block, and convert that to a "slim" lambda later on:
myList.sort(Comparator.comparing((String x) -> { return x.| }));
For the above case, the completion should work (IF you specify String as absolute type of the Comparator, as I have done in the example).
Issues like this stem from the question of how to interpret the characters and therefore deduce, what the programmer might intent to write (the process of auto completion and completion suggestion).
eclipse is very strong in isolating a reference to a named entity, when in regular code, like a method block, a for loop, or any other construct. That is why it works well there. The syntax tree is usually easy to process then.
However when using lambdas, eclipse (and any other IDE for that matter) have a harder time. This is due to the fact, that lambdas work by inferring a lot of implicit information, which would otherwise need to be written explicitly (for example in an explicit implementation of the interface).
If everything else fails, you can create the explicit interface at that position and then convert to a lambda after completing it.
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 :)
Rather than implicit conversion, is there a way to force the java compiler to issue an error when variables types do not match. For example:
int intValue=3;
double dblValue = 2.2;
double result;
result = 1/intValue*(intValue-dblValue);
In the example above java will implicitly convert (1/intValue) to an integer with the value 0.
What I want is for the compiler to issue an error when variable types don't match rather than implicitly converting.
Thanks in advance
Edit1: The equation above is just an example. I do know how to fix this issue by using either one of the solutions below:
result = 1.0/intValue*(intValue-dblValue);
or
result = 1/(double)intValue*((double)intValue-dblValue);
but thats not what I'm after. Thanks
Edit2: I was referring to type conversion not type casting. I'm looking for the compiler to enforce explicit type conversions.
I'm looking for something like this:
https://support.microsoft.com/en-us/help/311329/option-explicit-and-option-strict-in-visual-basic-.net-and-in-visual-basic
How about, rather than dividing two integers, you divide a double and an integer?
result = 1.0/intValue*(intValue-dblValue);
"Rather than implicit typecasting, is there a way to force the java compiler to issue an error when variables types do not match." It does issue an error when types don't match, or there'll be a loss of information. As pointed out in a comment above, there isn't any "type casting", or narrowing conversion to be specific, in your example. The compiler is doing exactly what it is supposed to, and no, you can't change that.
"What I want is for the compiler to ..." Sadly, what you want isn't considered by the compiler. It will only do what is specified for compliance with the Java language by the Java Language Specification and compatibility requirements.
In your case you specified a perfectly legal int operation requiring neither a widening nor narrowing conversion, so even if the compiler did care about what you want, there'd be nothing for it to complain about.
You can use lint tools like Findbugs and CheckStyle to preprocess your source for all kinds of bug risks, even custom rules. They might detect the use case of a programmer mistakenly ignoring associativity or type risks in mixed-type expressions. They're excellent tools; check them out.
I have below code snippet and this works fine. Shouldn't it throw compile time error because I have defined c as ArrayList which will contain String object but I am adding Integer object. So why it did not throw compile time/Run time error?
Collection c = new ArrayList<String>();
c.add(123);
I know below will throw compile time error but why not above. Whats the logical difference between both these code snippet?
Collection<String>() c = new ArrayList();
c.add(123);
The first code snippet does not result in a compile time error, because at the line
c.add(123)
the compiler inspects the type of c. Since you declared c as Collection, the compiler treats it as such. Since Collection offers a method add(Object), it is perfectly reasonable to add any object to the c, especially an integer. Note that this program will however result in a runtime-error, if you attempt to read back the collection values as Strings.
In your second code snippet you provide more information for the compiler to work with. In this snippet it knows that the Collection it deals with is an Collection<String>, which can only accept Strings. Thus, there is no method add(int) or add(Object), only add(String). This leads to a compile-time error.
why it did not throw compile time error?
Because it's not syntactically or semantically invalid, it's just unwise.
Note that most modern IDEs (e.g. Eclipse) can be configured to warn you about the unparameterised Collection c, and optionally to fail to compile.
In the first example, the collection is "raw". This will usually result in a warning but not an error (depending on your exact set-up). This is primary in order to be able to compile all the pre-Java 5 legacy code around.
The the second example, you assign a "raw" object to a parameterized version, which only can be done with an explicit cast.
1) What is the logical difference?
Above: A Collection can be declared without a generic type. This is called a raw type. The collection can then hold any kind of collection. Since, with a raw typed collection, at runtime you might use a collection of strings as a collection of integers causing a runtime exception the compiler will usually throw a warning. Since you have not typed the collection in the above example the compiler can not prevent these runtime exceptions. The warning can be ignored if you know what it is for and know what you are doing.
Below: But a variable declared as a Collection<String> cannot hold any kind of collection. It has to be a collection of the type String. It is strong typed. The compiler is correct to see this as an error.
2) Why does the above snippet not cause a compiler error?
Java is strong typed, which ensures type safety. The above snippet is not type safe, but allowed by Java nonetheless. This is probably for historical reasons: Generics were only introduced with Java 1.5, so if the above snippet would have caused a compile error then most Java 1.4 code would have been broken in the Java 1.5 compiler.
Not every programming language evolves in such a backward compatible manner (PHP for instance). Apparently backward compatibility was valued over type safety when introducing Java 1.5.
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.