I'm trying to run the following code which is compiled fine under JDK8 thanks to type inference:
public static <A,B> B convert(A a) {
return (B) new CB();
}
public static void main(String[] args) {
CA a = new CA();
CB b = convert(a); //this runs fine
List<CB> bl = Arrays.asList(b); //this also runs fine
List<CB> bl1 = Arrays.asList(convert(a)); //ClassCastException here
}
However, running this throws ClassCastException: CB cannot be cast to [Ljava.lang.Object, but the CB b = convert(a) works fine.
Any idea why?
Whenever you create a generic method with a signature that promises to return whatever the caller wishes, you are asking for trouble. You should have got an “unchecked” warning from the compiler which basically means: unexpected ClassCastExceptions may occur.
You expect the compiler to infer
List<CB> bl1 = Arrays.asList(YourClass.<CA,CB>convert(a));
whereas the compiler actually inferred
List<CB> bl1 = Arrays.asList(YourClass.<CA,CB[]>convert(a));
as far as I know, because it prefers method invocations not requiring a varargs packaging (which is compatible with pre-varargs code).
This fails because your convert method does not return the expected array type.
Related
I want to pass multiple optional objects in function as varags ?
Optional<ab> ab = Optional.of(ab);
Optional<cd> cd = Optional.of(cd);
Optional<dc> dc = Optional.of(dc);
Optional<ba> ba = Optional.of(ba);
data(ab, cd, dc, ba);
data(Optional<Object>... objects){...}
I am getting error if i don this, any suggestion how can be proceed?
It isn’t related to varargs. You can’t pass an Optional<SomeSpecificType> where an Optional<Object> is expected. They are not compatible.
Assume just (without varargs):
static void data(Optional<Object> object) {
// …
}
Now if we try
Optional<String> ab = Optional.of("");
data(ab);
In my Eclipse I get this error message:
The method data(Optional<Object>) in the type MyClass is not
applicable for the arguments (Optional<String>)
Java generics are defined with this restriction. You also cannot pass, for example a List<String> where a List<Object> is expected.
You can overcome the limitation by declaring the method generic too:
static <T> void data(Optional<T> object) {
// …
}
Or just like this:
static void data(Optional<?> object) {
// …
}
With any of these two declarations the call above is OK.
BTW, #HadiJ is correct in the comment: Optional is meant for return values for from methods that may or may not be there. They have very few other good uses, and as parameters is not one of them. It seems to me that for your use case you should just pass the arguments that are there and leave out those that aren’t. The your data method may receive a longer or shorter argument array, but will just have to handle all elements of the array without caring about Optional. And passing String, Integer, LocalDate, etc, to a method declared void data(Object... objs) is straightforward and poses no problem.
I'm coding in IntelliJ IDEA. When debugging my application, I can't use some default method implementations in Watches.
Here is a condensed example:
public class Friendship {
interface Friend {
default void sayHiTo(Friend friend) {
System.out.println("Hi, " + friend.hashCode());
}
default int amountOfHands() {
return 2;
}
}
public static class BasicFriend implements Friend {
int numberOfFaces() {
return 1;
}
}
public static void main(String[] args) {
System.out.println("Put a breakpoint here");
}
}
In main() method I put a breakpoint and set up three watches:
// Default interface method with dependency
new BasicFriend().sayHiTo(new BasicFriend())
// Default interface method without dependency
new BasicFriend().amountOfHands()
// Class method
new BasicFriend().numberOfFaces()
The first watch throws NoSuchMethodException complaining that method Friendship$BasicFriend.sayHiTo() doesn't exist.
The second watch runs successfully, but strangely it reports a boxed object
{java.lang.Integer#537} "2" instead of just a primitive 2.
The third watch reports a primitive 1, just as expected.
Why is the first watch not working? Is this a bug? Is this actually IDE related? Is it because of some conceptual flaw of default methods? Should it be working as I want it to in the first place? Is the strange result of the second watch somehow related to the issue in the first watch?
Prior to JDK 8u40, default and static interface methods were not supported by JDI (Java Debugger Interface), JDWP (Java Debugger Wire Protocol) and JDB (the standard Java debugger). This is bug JDK-8042123, which is recorded as fixed in 8u40 and a corresponding blurb appears in the 8u40 release notes.
Update to 8u40 or later to fix this issue, at least on the JDK side.
From the bug description, it looks like debugger-side changes are also required, to avoid casting com.sun.jdi.InterfaceType objects to com.sun.jdi.ClassType, but instead call InterfaceType.invokeMethod() directly.
In the specific case of IntelliJ, Suseika confirmed in a comment that 14.1.2 has mostly fixed the issue (except the unexpected boxing), though Mike Kobit still experiences this problem on that version with a ClassCastException suggestive of the incorrect cast above.
I just moved to Java 8 and I am getting some compilation errors that I don't really understand how to overcome.
The following code does not compile:
Mockito.when(
jdbcTemplate.query(Mockito.eq(expectedQuery1),
Mockito.any(ResultSetExtractor.class))).thenReturn(mockReturn1);
With error:
The method query(String, ResultSetExtractor<T>) in the type JdbcTemplate is not
applicable for the arguments (String, ResultSetExtractor)
I have tried another approach from Java 1.8 with Mockito 1.9.5 gives compile errors:
Mockito.when(jdbcTemplate.query(Mockito.eq(expectedQuery1), Mockito.any()))
.thenReturn(mockReturn1);
now I am getting the following error:
The method when(T) in the type Mockito is not applicable for the arguments (void)
how exactly does this supposed to work and why doesn't it work in the first place
Add a type witness to help the Eclipse compiler figure it all out:
Mockito.when(jdbcTemplate.query(Mockito.eq(expectedQuery1),
Mockito.<ResultSetExtractor<TYPE>> any())).thenReturn(mockReturn1);
Ensure you replace TYPE with the type of mockReturn1. E.g.
String mockReturn1 = "result";
Mockito.when(jdbcTemplate.query(Mockito.eq(expectedQuery1),
Mockito.<ResultSetExtractor<String>> any())).thenReturn(mockReturn1);
I expect the Oracle Java 8 compiler could figure this out itself, due to its improved type inference capabilities.
What is happening is that you are passing mockito ResultSetExtractor.class, which is of type Class<ResultSetExtractor>, but this is incorrect, because it is expecting a Class<ResultSetExtractor<T>>.
To overcome this problem, define a method as follows:
#SuppressWarnings( "rawtypes" )
public static <T> Class<T> uncheckedClassCast( Class clazz )
{
if( clazz == null )
return null;
#SuppressWarnings( "unchecked" )
Class<T> result = (Class<T>)clazz;
return result;
}
And use it as follows:
Class<ResultSetExtractor<T>> resultSetExtractorClass =
uncheckedClassCast( ResultSetExtractor.class );
Then, in your calls to mockito (or anything else) use resultSetExtractorClass instead of ResultSetExtractor.class.
I've just modified a method for handling my DDD commands (previously it had no return type):
public static CommandResult<TReturn> Execute<TCommand, TReturn>(TCommand command)
where TCommand : IDomainCommand
{
var handler = IoCFactory.GetInstance<ICommandHandler<TCommand, TReturn>>();
return handler.Handle(command);
}
The method is fine, and does what I want it to do, however using it creates some fugly code:
CommandResult<Customer> result =
DomainCommands.Execute<CustomerCreateCommand, Customer>
(
new CustomerCreateCommand(message)
);
Before I added the Customer return type TReturn, it was nice and tidy and the method could infer the types from its usage. However that's no longer possible.
Is there any way using any new C# features that I could rewrite the above to make it tidier, i.e. using Func, Action, Expression, etc? I'm probably expecting the impossible, but I'm getting fed up of writing so much code to just call a single method that used to be very simple.
One option to reduce it slightly is to have a static generic type for the type parameter that can't be inferred, allowing you to have a generic method with just one type parameter that can be inferred:
public static class DomainCommands<TReturn>
{
public static CommandResult<TReturn> Execute<TCommand>(TCommand command)
where TCommand : IDomainCommand
{
var handler = IoCFactory.GetInstance<ICommandHandler<TCommand, TReturn>>();
return handler.Handle(command);
}
}
Then:
var result = DomainCommands<Customer>.Execute(new CustomerCreateCommand(msg));
It's not much nicer, but it's slightly better. Of course, if the domain command type itself could be generic, that might help - so CustomerCreateCommand would implement IDomainCommand<Customer> for example. If you still needed a nongeneric IDomainCommand, you could make IDomainCommand<T> derive from IDomainCommand.
Basically at work I commonly run into code like:
double pricediff = 0.0;
if(!string.IsNullOrEmpty(someVariable.ToString()))
pricediff = Convert.ToDouble(someVariable);
Instead of something like:
double pricediff = 0.0;
Double.TryParse(someVariable, out pricediff);
Is there a setting within Visual Studio that can produce a warning whenever a method such as Convert.Double is used that can throw an exception and the method is not contained within a try{} block?
No there is not. Part of the reason why is that practically any method out there can throw an exception. It would have to issue a warning for almost every method as virtually any method can raise the following
StackOverflowException
OutOfMemoryException
Add on top of that the much more likely NullReferenceException and essentially every method would be marked as "can throw".
It would be reasonable though to create a feature that marks for explicitly thrown exceptions. VS does not have this feature but R# does (IIRC). However even that is not foolproof because you can't see through interfaces.
interface IExample {
void Method();
}
class Class1 : IExample() {
void Method() { throw new Exception(); }
}
class Class2 : IExample() {
void Method() {}
}
...
IExample v1 = ...;
v1.Method();
In this same Method may or may not throw. Whether it does or not cannot be definitively determined by static analysis in all cases.